<?PHP  // $Id: lib.php,v 1.118.2.34 2006/02/16 22:00:32 gustav_delius Exp $

// SOME CONFIGURATIONS FOR THIS MODULE

if (!isset($CFG->aca_maxbytes)) {
    set_config("aca_maxbytes", 1024000);  // Default maximum size for all assignments
}

//temporary dir for unzip uploaded files
$ACACFG->unzipdir = $CFG->dataroot.'/temp/aca/';

// autokill script
$ACACFG->autokill = "/home/jura/myexec";
// default timeout for autokill (seconds)
$ACACFG->killtimeout = 60;

// plagiat detection main variables
$ACACFG->newpath="/home/jura/yap/tmp_tokens";
$ACACFG->tmppath="/home/jura/tmp";

$ACACFG->tokenizer_c="/home/jura/yap/tokenize_C";
$ACACFG->tokenizer_pascal="/home/jura/yap/tokenizers/tokenize_PASCAL2";
$ACACFG->tokenizer_php="/home/jura/yap/tokenizers/tokenize_PHP";

$ACACFG->simchecker="/home/jura/yap/yap3/check2";

// maximal length of result string
$ACACFG->maxstrreslenght = 80;

/**
 * ac assignment_base is the base class for ac assignment types
 *
 * This class provides all the functionality for an ac assignment
 */

/*
 * Standard base class for all aca submodules (langtypes).
 *
 */
class aca_base {

    var $cm;
    var $course;
    var $assignment;

    /**
     * Constructor for the base ac assignment class
     *
     * Constructor for the base ac assignment class.
     * If cmid is set create the cm, course, ac assignment objects.
     *
     * @param cmid   integer, the current course module id - not set for new assignments
     * @param assignment   object, usually null, but if we have it we pass it to save db access
     */
    function aca_base($cmid=0, $assignment=NULL, $cm=NULL, $course=NULL) {

        global $CFG;

        if ($cmid) {
            if ($cm) {
                $this->cm = $cm;
            } else if (! $this->cm = get_record('course_modules', 'id', $cmid)) {
                error('Course Module ID was incorrect');
            }

            if ($course) {
                $this->course = $course;
            } else if (! $this->course = get_record('course', 'id', $this->cm->course)) {
                error('Course is misconfigured');
            }

            if ($assignment) {
                $this->assignment = $assignment;
            } else if (! $this->assignment = get_record('aca', 'id', $this->cm->instance)) {
                error('assignment ID was incorrect');
            }
            
            // base strings
            $this->strassignment = get_string('modulename', 'aca');
            $this->strassignments = get_string('modulenameplural', 'aca');
            $this->strsubmissions = get_string('submissions', 'aca');
            $this->strlastmodified = get_string('lastmodified');

            if ($this->course->category) {
                $this->navigation = "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
            } else {
                $this->navigation = "<a target=\"{$CFG->framename}\" href=\"index.php?id={$this->course->id}\">$this->strassignments</a> ->";
            }

            $this->pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment.': '.format_string($this->assignment->name,true));

            if (!$this->cm->visible and !isteacher($this->course->id)) {
                $pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment);
                print_header($pagetitle, $this->course->fullname, "$this->navigation $this->strassignment", 
                             "", "", true, '', navmenu($this->course, $this->cm));
                notice(get_string("activityiscurrentlyhidden"), "$CFG->wwwroot/course/view.php?id={$this->course->id}");
            }
            $this->currentgroup = get_current_group($this->course->id);
        }

    /// Set up things for a HTML editor if it's needed
        if ($this->usehtmleditor = can_use_html_editor()) {
            $this->defaultformat = FORMAT_HTML;
        } else {
            $this->defaultformat = FORMAT_MOODLE;
        }
    }

    /*
     * Display the AC assignment to students (sub-modules will most likely override this)
     */
    function view() {

        add_to_log($this->course->id, "aca", "view", "view.php?id={$this->cm->id}", 
                   $this->assignment->id, $this->cm->id);

        $this->view_header();

        $this->view_intro();

        $this->view_dates();

        $this->view_feedback();

        $this->view_footer();
    }

    /*
     * Display the top of the view.php page, this doesn't change much for submodules
     */
    function view_header($subpage='') {

        global $CFG;

        if ($subpage) {
            $extranav = '<a target="'.$CFG->framename.'" href="view.php?id='.$this->cm->id.'">'.
                          format_string($this->assignment->name,true).'</a> -> '.$subpage;
        } else {
            $extranav = ' '.format_string($this->assignment->name,true);
        }
        
        $navigation = build_navigation($this->navigation.$extranav);

        print_header($this->pagetitle, $this->course->fullname, $navigation, '', '', 
                     true, update_module_button($this->cm->id, $this->course->id, $this->strassignment), 
                     navmenu($this->course, $this->cm));

        echo '<div class="reportlink">'.$this->submittedlink().'</div>';
    }


    /*
     * Display the assignment intro
     */
    function view_intro() {
        print_simple_box_start('center', '', '', '', 'generalbox', 'intro');
        $formatoptions = new stdClass;
        $formatoptions->noclean = true;
        echo format_text($this->assignment->description, $this->assignment->format, $formatoptions);
        print_simple_box_end();
    }

    /*
     * Display the assignment dates
     */
    function view_dates() {
        if (!$this->assignment->timeavailable && !$this->assignment->timedue) {
            return;
        }

        print_simple_box_start('center', '', '', '', 'generalbox', 'dates');
        echo '<table>';
        if ($this->assignment->timeavailable) {
            echo '<tr><td class="c0">'.get_string('availabledate','aca').':</td>';
            echo '    <td class="c1">'.userdate($this->assignment->timeavailable).'</td></tr>';
        }
        if ($this->assignment->timedue) {
            echo '<tr><td class="c0">'.get_string('duedate','aca').':</td>';
            echo '    <td class="c1">'.userdate($this->assignment->timedue).'</td></tr>';
        }
        echo '</table>';
        print_simple_box_end();
    }


    /*
     * Display the bottom of the view.php page, this doesn't change much for submodules
     */
    function view_footer() {
        print_footer($this->course);
    }

    function view_feedback($submission=NULL) {
        global $USER;

        if (!$submission) { /// Get submission for this assignment
            $submission = $this->get_submission($USER->id);
        }

        if (empty($submission->timemarked)) {   /// Nothing to show, so print nothing
            return;
        }

    /// We need the teacher info
        if (! $teacher = get_record('user', 'id', $submission->teacher)) {
            error('Could not find the teacher');
        }

    /// Print the feedback
        print_heading(get_string('feedbackfromteacher', 'aca', $this->course->teacher));

        echo '<table cellspacing="0" class="feedback">';

        echo '<tr>';
        echo '<td class="left picture">';
        print_user_picture($teacher->id, $this->course->id, $teacher->picture);
        echo '</td>';
        echo '<td class="topic">';
        echo '<div class="from">';
        echo '<div class="fullname">'.fullname($teacher).'</div>';
        echo '<div class="time">'.userdate($submission->timemarked).'</div>';
        echo '</div>';
        $this->print_user_files($submission->userid);
        echo '</td>';
        echo '</td>';
        echo '</tr>';

        echo '<tr>';
        echo '<td class="left side">&nbsp;</td>';
        echo '<td class="content">';
        if ($this->assignment->grade) {
            echo '<div class="grade">';
            echo get_string("grade").': '.$this->display_grade($submission->grade);
            echo '</div>';
            echo '<div class="clearer"></div>';
        }

        echo '<div class="comment">';
        echo format_text($submission->comment, $submission->format);
        echo '</div>';
        echo '</tr>';

        echo '</table>';
    }

    /* 
     * Returns a link with info about the state of the assignment submissions
     */
    function submittedlink() {
        global $USER;

        $submitted = '';

        if (isteacher($this->course->id)) {
            if (!isteacheredit($this->course->id) and user_group($this->course->id, $USER->id)) {
                $count = $this->count_real_submissions($this->currentgroup);  // Only their group
            } else {
                $count = $this->count_real_submissions();                     // Everyone
            }
            $submitted = '<a href="submissions.php?id='.$this->cm->id.'">'.
                         get_string('viewsubmissions', 'aca', $count).'</a>';
        } else {
            if (isset($USER->id)) {
                if ($submission = $this->get_submission($USER->id)) {
                    if ($submission->timemodified) {
                        if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) {
                            $submitted = '<span class="early">'.userdate($submission->timemodified).'</span>';
                        } else {
                            $submitted = '<span class="late">'.userdate($submission->timemodified).'</span>';
                        }
                    }
                }
            }
        }

        return $submitted;
    }

    /*
     * Print the start of the setup form for the current AC assignment type
     */
    function setup(&$form, $action='') {
        global $CFG, $THEME;

        if (empty($this->course)) {
            if (! $this->course = get_record("course", "id", $form->course)) {
                error("Course is misconfigured");
            }
        }
        
        if (empty($action)) {   // Default destination for this form
            $action = $CFG->wwwroot.'/course/mod.php';
        }

        if (empty($form->name)) {
            $form->name = "";
        }
        if (empty($form->langtype)) {
            //PAJA modify 21.4.2006 15:06:13
            $form->langtype = "offline";
        } else {
            $form->langtype = clean_param($form->langtype, PARAM_SAFEDIR);
        }
        if (empty($form->description)) {
            $form->description = "";
        }

        $strname    = get_string('name');
        $strassignments = get_string('modulenameplural', 'aca');
        $strheading = empty($form->name) ? get_string("type".strtolower($form->langtype),'aca') : s(format_string(stripslashes($form->name),true));

        $navigation = build_navigation("<a href=\"$CFG->wwwroot/mod/aca/index.php?id={$this->course->id}\">$strassignments</a> -> $strheading");
        
        print_header($this->course->shortname.': '.$strheading, "$strheading",$navigation);


        print_simple_box_start('center', '70%');
        print_heading(get_string('type'.strtolower($form->langtype),'aca'));
        print_simple_box(get_string('help'.strtolower($form->langtype), 'aca'), 'center');
        include("$CFG->dirroot/mod/aca/type/common.html");

        include("$CFG->dirroot/mod/aca/type/".$form->langtype."/mod.html");
        $this->setup_end(); 
    }

    /*
     * Print the end of the setup form for the current assignment type
     */
    function setup_end() {
        global $CFG;

        include($CFG->dirroot.'/mod/aca/type/common_end.html');

        print_simple_box_end();

        if ($this->usehtmleditor) {
            use_html_editor();
        }

        print_footer($this->course);
    }

    /**
     * function is called from function aca_add_instance (botttom of this script)
     **/
    function add_instance($assignment) {
        // Given an object containing all the necessary data,
        // (defined by the form in mod.html) this function
        // will create a new instance and return the id number
        // of the new instance.

        $assignment->timemodified = time();
        if (empty($assignment->dueenable)) {
            $assignment->timedue = 0;
            $assignment->preventlate = 0;
        } else {
            $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth, 
                                                  $assignment->dueday, $assignment->duehour, 
                                                  $assignment->dueminute);
        }
        if (empty($assignment->availableenable)) {
            $assignment->timeavailable = 0;
        } else {
            $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth, 
                                                        $assignment->availableday, $assignment->availablehour, 
                                                        $assignment->availableminute);
        }

        if ($returnid = insert_record("aca", $assignment)) {

            if ($assignment->timedue) {
                $event = NULL;
                $event->name        = $assignment->name;
                $event->description = $assignment->description;
                $event->courseid    = $assignment->course;
                $event->groupid     = 0;
                $event->userid      = 0;
                $event->modulename  = 'aca';
                $event->instance    = $returnid;
                $event->eventtype   = 'due';
                $event->timestart   = $assignment->timedue;
                $event->timeduration = 0;

                add_event($event);
            }
        }
        
        //PAJA added: uploading sourcefile and update DB
        if ($returnid) {
          $assignment->id = $returnid;
          $assignment->sourcefile = $this->upload_source($assignment);
          update_record('aca',$assignment);
        }

        return $returnid;
    }
    
    /**
     * function is called from function aca_delete_instance (botttom of this script)
     **/
    function delete_instance($assignment) {
        $result = true;

        // test vectors
        if (! delete_records('aca_tv_active', 'acaid', $assignment->id)) {
            $result = false;
        }
        if (! delete_records('aca_tv_results', 'acaid', $assignment->id)) {
            $result = false;
        }
        
        // plagiat detectors
        if (! delete_records('aca_pd_active', 'acaid', $assignment->id)) {
            $result = false;
        }
        if (! delete_records('aca_pd_similarity', 'acaid', $assignment->id)) {
            $result = false;
        }

        // submissions
        if (! delete_records('aca_submissions', 'acaid', $assignment->id)) {
            $result = false;
        }
        
        // assignment
        if (! delete_records('aca', 'id', $assignment->id)) {
            $result = false;
        }

        if (! delete_records('event', 'modulename', 'aca', 'instance', $assignment->id)) {
            $result = false;
        }

        return $result;
    }

    /**
     * function is called from function aca_update_instance (botttom of this script)
     **/
    function update_instance($assignment) {
        // Given an object containing all the necessary data,
        // (defined by the form in mod.html) this function
        // will create a new instance and return the id number
        // of the new instance.

        $assignment->timemodified = time();
        if (empty($assignment->dueenable)) {
            $assignment->timedue = 0;
            $assignment->preventlate = 0;
        } else {
            $assignment->timedue = make_timestamp($assignment->dueyear, $assignment->duemonth, 
                                                  $assignment->dueday, $assignment->duehour, 
                                                  $assignment->dueminute);
        }
        if (empty($assignment->availableenable)) {
            $assignment->timeavailable = 0;
        } else {
            $assignment->timeavailable = make_timestamp($assignment->availableyear, $assignment->availablemonth, 
                                                        $assignment->availableday, $assignment->availablehour, 
                                                        $assignment->availableminute);
        }

        $assignment->id = $assignment->instance;
        
        //PAJA added: upload sourcefile if needed
        $assignment->sourcefile = $this->upload_source($assignment);

        if ($returnid = update_record('aca', $assignment)) {

            if ($assignment->timedue) {
                $event = NULL;

                if ($event->id = get_field('event', 'id', 'modulename', 'aca', 'instance', $assignment->id)) {

                    $event->name        = $assignment->name;
                    $event->description = $assignment->description;
                    $event->timestart   = $assignment->timedue;

                    update_event($event);
                } else {
                    $event = NULL;
                    $event->name        = $assignment->name;
                    $event->description = $assignment->description;
                    $event->courseid    = $assignment->course;
                    $event->groupid     = 0;
                    $event->userid      = 0;
                    $event->modulename  = 'aca';
                    $event->instance    = $assignment->id;
                    $event->eventtype   = 'due';
                    $event->timestart   = $assignment->timedue;
                    $event->timeduration = 0;

                    add_event($event);
                }
            } else {
                delete_records('event', 'modulename', 'aca', 'instance', $assignment->id);
            }
        }

        return $returnid;
    }

    /*
     * Top-level function for handling of submissions called by submissions.php
     *  
     */
    function submissions($mode) {
        ///The main switch is changed to facilitate
        ///1) Batch fast grading
        ///2) Skip to the next one on the popup
        ///3) Save and Skip to the next one on the popup
        
        //make user global so we can use the id
        global $USER;
        
        $testall = optional_param('testall',0);
        if ($testall!=0) {
            $this->process_test_all($testall);
        }
        
        switch ($mode) {
            case 'grade':                         // We are in a popup window grading
                if ($submission = $this->process_feedback()) {
                    //IE needs proper header with encoding
                    print_header(get_string('feedback', 'aca').':'.format_string($this->assignment->name));
                    print_heading(get_string('changessaved'));
                    $this->update_main_listing($submission);
                }
                close_window();
                break;

            case 'single':                        // We are in a popup window displaying submission
                $this->display_submission();
                break;

            case 'all':                           // Main window, display everything
                $this->display_submissions();
                break;

            case 'fastgrade':
                ///do the fast grading stuff  - this process should work for all 3 subclasses
                $grading    = false;
                $commenting = false;
                $col        = false;
                if (isset($_POST['comment'])) {
                    $col = 'comment';
                    $commenting = true;
                }
                if (isset($_POST['menu'])) {
                    $col = 'menu';
                    $grading = true;
                }
                if (!$col) {
                    //both comment and grade columns collapsed..
                    $this->display_submissions();            
                    break;
                }
                foreach ($_POST[$col] as $id => $unusedvalue){

                    $id = (int)$id; //clean parameter name
                    if (!$submission = $this->get_submission($id)) {
                        $submission = $this->prepare_new_submission($id);
                        $newsubmission = true;
                    } else {
                        $newsubmission = false;
                    }

                    //for fast grade, we need to check if any changes take place
                    $updatedb = false;

                    if ($grading) {
                        $grade = $_POST['menu'][$id];
                        $updatedb = $updatedb || ($submission->grade != $grade);
                        $submission->grade = $grade;
                    } else {
                        if (!$newsubmission) {
                            unset($submission->grade);  // Don't need to update this.
                        }
                    }
                    if ($commenting) {
                        $commentvalue = trim($_POST['comment'][$id]);
                        $updatedb = $updatedb || ($submission->comment != stripslashes($commentvalue));
                        $submission->comment = $commentvalue;
                    } else {
                        unset($submission->comment);  // Don't need to update this.
                    }

                    $submission->teacher    = $USER->id;
                    $submission->mailed     = $updatedb?0:$submission->mailed;//only change if it's an update
                    $submission->timemarked = time();

                    //if it is not an update, we don't change the last modified time etc.
                    //this will also not write into database if no comment and grade is entered.

                    if ($updatedb){
                        if ($newsubmission) {
                            if (!insert_record('aca_submissions', $submission)) {
                                return false;
                            }
                        } else {
                            if (!update_record('aca_submissions', $submission)) {
                                return false;
                            }
                        }            
                        //add to log only if updating
                        add_to_log($this->course->id, 'aca', 'update grades', 
                                   'submissions.php?id='.$this->assignment->id.'&user='.$submission->userid, 
                                   $submission->userid, $this->cm->id);             
                    }
                        
                } 
                print_heading(get_string('changessaved'));
                $this->display_submissions();            
                break;


            case 'next':
                /// We are currently in pop up, but we want to skip to next one without saving.
                ///    This turns out to be similar to a single case
                /// The URL used is for the next submission.
                
                $this->display_submission();
                break;
                
            case 'saveandnext':
                ///We are in pop up. save the current one and go to the next one.
                //first we save the current changes
                if ($submission = $this->process_feedback()) {
                    //print_heading(get_string('changessaved'));
                    $this->update_main_listing($submission);
                }
                
                //then we display the next submission
                $this->display_submission();
                break;
            
            default:
                echo "something seriously is wrong!!";
                break;                    
        }
    }
    
    /**
     * function that updates the listing on the main script from popup using javascript
     **/
    function update_main_listing($submission) {
        global $SESSION;
        
        $perpage = get_user_preferences('aca_perpage', 10);

        $quickgrade = get_user_preferences('aca_quickgrade', 0);
        
        /// Run some Javascript to try and update the parent page
        echo '<script type="text/javascript">'."\n<!--\n";
        if (empty($SESSION->flextable['mod-aca-submissions']->collapse['comment'])) {
            if ($quickgrade){
                echo 'opener.document.getElementById("comment['.$submission->userid.']").value="'
                .trim($submission->comment).'";'."\n";
             } else {
                echo 'opener.document.getElementById("com'.$submission->userid.
                '").innerHTML="'.shorten_text(trim(strip_tags($submission->comment)), 15)."\";\n";
            }
        }

        if (empty($SESSION->flextable['mod-aca-submissions']->collapse['grade'])) {
            //echo optional_param('menuindex');
            if ($quickgrade){
                echo 'opener.document.getElementById("menumenu['.$submission->userid.
                ']").selectedIndex="'.optional_param('menuindex', 0, PARAM_INT).'";'."\n";
            } else {
                echo 'opener.document.getElementById("g'.$submission->userid.'").innerHTML="'.
                $this->display_grade($submission->grade)."\";\n";
            }            
        }    
        //need to add student's assignments in there too.
        if (empty($SESSION->flextable['mod-aca-submissions']->collapse['timemodified']) &&
            $submission->timemodified) {
            echo 'opener.document.getElementById("ts'.$submission->userid.
                 '").innerHTML="'.addslashes($this->print_student_answer($submission->userid)).userdate($submission->timemodified)."\";\n";
        }
        
        if (empty($SESSION->flextable['mod-aca-submissions']->collapse['timemarked']) &&
            $submission->timemarked) {
            echo 'opener.document.getElementById("tt'.$submission->userid.
                 '").innerHTML="'.userdate($submission->timemarked)."\";\n";
        }
        
        if (empty($SESSION->flextable['mod-aca-submissions']->collapse['status'])) {
           echo 'opener.document.getElementById("up'.$submission->userid.'").className="s1";';
            $buttontext = get_string('update');
            $button = link_to_popup_window ('/mod/aca/submissions.php?id='.$this->cm->id.'&amp;userid='.$submission->userid.'&amp;mode=single'.'&amp;offset='.optional_param('offset', '', PARAM_INT), 
                      'grade'.$submission->userid, $buttontext, 450, 700, $buttontext, 'none', true, 'button'.$submission->userid);
               echo 'opener.document.getElementById("up'.$submission->userid.'").innerHTML="'.addslashes($button).'";';               
        }
        echo "\n-->\n</script>";
        flush();
    }

    /*
     *  Display a grade in user-friendly form, whether it's a scale or not
     *  
     */
    function display_grade($grade) {

        static $scalegrades = array();   // Cache scales for each assignment - they might have different scales!!

        if ($this->assignment->grade >= 0) {    // Normal number
            if ($grade == -1) {
                return '-';
            } else {
                return $grade.' / '.$this->assignment->grade;
            }

        } else {                                // Scale
            if (empty($scalegrades[$this->assignment->id])) {
                if ($scale = get_record('scale', 'id', -($this->assignment->grade))) {
                    $scalegrades[$this->assignment->id] = make_menu_from_list($scale->scale);
                } else {
                    return '-';
                }
            }
            if (isset($scalegrades[$this->assignment->id][$grade])) {
                return $scalegrades[$this->assignment->id][$grade];
            }
            return '-';
        }
    }

    /*
     *  Display a single submission, ready for grading on a popup window
     *  
     */
    function display_submission() {
    
        global $CFG;
        
        $userid = required_param('userid', PARAM_INT);
        $offset = required_param('offset', PARAM_INT);//offset for where to start looking for student.

        if (!$user = get_record('user', 'id', $userid)) {
            error('No such user!');
        }

        if (!$submission = $this->get_submission($user->id)) {
            $submission = $this->prepare_new_submission($userid);
        }

        if ($submission->timemodified > $submission->timemarked) {
            $subtype = 'assignmentnew';
        } else {
            $subtype = 'assignmentold';
        }

        ///construct SQL, using current offset to find the data of the next student
        $course     = $this->course;
        $assignment = $this->assignment;
        $cm         = $this->cm;
    
        if ($groupmode = groupmode($course, $cm)) {   // Groups are being used
            $currentgroup = setup_and_print_groups($course, $groupmode, 'submissions.php?id='.$this->cm->id);
        } else {
            $currentgroup = false;
        }

    /// Get all teachers and students
        if ($currentgroup) {
            $users = get_group_users($currentgroup);
        } else {
            $users = get_course_users($course->id);
        }

        $select = 'SELECT u.id, u.id, u.firstname, u.lastname, u.picture,'.
                  's.id AS submissionid, s.grade, s.comment, s.timemodified, s.timemarked, ((s.timemarked > 0) AND (s.timemarked >= s.timemodified)) AS status ';
        $sql = 'FROM '.$CFG->prefix.'user u '.
               'LEFT JOIN '.$CFG->prefix.'aca_submissions s ON u.id = s.userid AND s.acaid = '.$this->assignment->id.' '.
               'WHERE u.id IN ('.implode(',', array_keys($users)).') ';
               
        require_once($CFG->libdir.'/tablelib.php');
        if($sort = flexible_table::get_sql_sort('mod-aca-submissions')) {
            $sort = 'ORDER BY '.$sort.' ';
        }

        $limit = sql_paging_limit($offset+1, 1);

        $nextid = 0;
        if (($auser = get_record_sql($select.$sql.$sort.$limit, false, true)) !== false) {
            $nextid = $auser->id;
        }

        print_header(get_string('feedback', 'aca').':'.fullname($user, true).':'.format_string($this->assignment->name));

        ///SOme javascript to help with setting up >.>
        
        echo '<script type="text/javascript">'."\n";
        echo 'function setNext(){'."\n";
        echo 'document.submitform.mode.value=\'next\';'."\n";
        echo 'document.submitform.userid.value="'.$nextid.'";'."\n";
        echo '}'."\n";
        
        echo 'function saveNext(){'."\n";
        echo 'document.submitform.mode.value=\'saveandnext\';'."\n";
        echo 'document.submitform.userid.value="'.$nextid.'";'."\n";
        echo 'document.submitform.saveuserid.value="'.$userid.'";'."\n";
        echo 'document.submitform.menuindex.value = document.submitform.grade.selectedIndex;'."\n";
        echo '}'."\n";
            
        echo '</script>'."\n";
        echo '<table cellspacing="0" class="feedback '.$subtype.'" >';

        ///Start of teacher info row

        echo '<tr>';
        echo '<td width="35" valign="top" class="picture teacher">';
        if ($submission->teacher) {
            $teacher = get_record('user', 'id', $submission->teacher);
        } else {
            global $USER;
            $teacher = $USER;
        }
        print_user_picture($teacher->id, $this->course->id, $teacher->picture);
        echo '</td>';
        echo '<td class="content">';
        echo '<form name="submitform" action="submissions.php" method="post">';
        echo '<input type="hidden" name="offset" value="'.++$offset.'">';
        echo '<input type="hidden" name="userid" value="'.$userid.'" />';
        echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
        echo '<input type="hidden" name="mode" value="grade" />';
        echo '<input type="hidden" name="menuindex" value="0" />';//selected menu index
        
        //new hidden field, initialized to -1.
        echo '<input type="hidden" name="saveuserid" value="-1" />';
        if ($submission->timemarked) {
            echo '<div class="from">';
            echo '<div class="fullname">'.fullname($teacher, true).'</div>';
            echo '<div class="time">'.userdate($submission->timemarked).'</div>';
            echo '</div>';
        }
        echo '<div class="grade">'.get_string('grade').':';
        choose_from_menu(make_grades_menu($this->assignment->grade), 'grade', $submission->grade, get_string('nograde'), '', -1);
        echo '</div>';
        echo '<div class="clearer"></div>';

        $this->preprocess_submission($submission);

        echo '<br />';
        print_textarea($this->usehtmleditor, 14, 58, 0, 0, 'comment', $submission->comment, $this->course->id);

        if ($this->usehtmleditor) { 
            echo '<input type="hidden" name="format" value="'.FORMAT_HTML.'" />';
        } else {
            echo '<div align="right" class="format">';
            choose_from_menu(format_text_menu(), "format", $submission->format, "");
            helpbutton("textformat", get_string("helpformatting"));
            echo '</div>';
        }

        ///Print Buttons in Single View
        echo '<div class="buttons" align="center">';
        echo '<input type="submit" name="submit" value="'.get_string('savechanges').'" onclick = "document.submitform.menuindex.value = document.submitform.grade.selectedIndex" />';
        echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />';
        //if there are more to be graded.
        if ($nextid) {
            echo '<input type="submit" name="saveandnext" value="'.get_string('saveandnext').'" onclick="saveNext()" />';
            echo '<input type="submit" name="next" value="'.get_string('next').'" onclick="setNext();" />';
        }
        echo '</div>';
        echo '</form>';
        echo '</td></tr>';
        
        ///End of teacher info row, Start of student info row
        echo '<tr>';
        echo '<td width="35" valign="top" class="picture user">';
        print_user_picture($user->id, $this->course->id, $user->picture);
        echo '</td>';
        echo '<td class="topic">';
        echo '<div class="from">';
        echo '<div class="fullname">'.fullname($user, true).'</div>';
        if ($submission->timemodified) {
            echo '<div class="time">'.userdate($submission->timemodified).
                                     $this->display_lateness($submission->timemodified).'</div>';
        }
        echo '</div>';
        echo $this->print_student_answer($user->id);
        echo '</td>';
        echo '</tr>';
        
        ///End of student info row
        
        echo '</table>';

        if ($this->usehtmleditor) {
            use_html_editor();
        }

        print_footer('none');
    }

    /*
     *  Preprocess submission before grading
     */
    function preprocess_submission(&$submission) {
    }

    /*
     *  Display all the submissions ready for grading
     */
    function display_submissions() {

        global $CFG, $db, $USER;

        /* first we check to see if the form has just been submitted
         * to request user_preference updates
         */
         
        if (isset($_POST['updatepref'])){
            $perpage = optional_param('perpage', 10, PARAM_INT);
            $perpage = ($perpage <= 0) ? 10 : $perpage ;
            set_user_preference('aca_perpage', $perpage);
            set_user_preference('aca_quickgrade', optional_param('quickgrade',0, PARAM_BOOL));
        }

        /* next we get perpage and quickgrade (allow quick grade) params 
         * from database
         */
        $perpage    = get_user_preferences('aca_perpage', 10);
        $quickgrade = get_user_preferences('aca_quickgrade', 0);
        
        $teacherattempts = true; /// Temporary measure
        $page    = optional_param('page', 0, PARAM_INT);
        $strsaveallfeedback = get_string('saveallfeedback', 'aca');

    /// Some shortcuts to make the code read better
        
        $course     = $this->course;
        $assignment = $this->assignment;
        $cm         = $this->cm;
        
        $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet

        add_to_log($course->id, 'aca', 'view submission', 'submissions.php?id='.$this->assignment->id, $this->assignment->id, $this->cm->id);
        
        $navigation = build_navigation('<a href="view.php?a='.$this->assignment->id.'">'.format_string($this->assignment->name,true).'</a> -> '. $this->strsubmissions);
        print_header_simple(format_string($this->assignment->name,true), "", $navigation, '', '', true, update_module_button($cm->id, $course->id, $this->strassignment), navmenu($course, $cm));

        $tablecolumns = array('picture', 'fullname', 'grade', 'comment', 'timemodified', 'timemarked', 'status');
        $tableheaders = array('', get_string('fullname'), get_string('grade'), get_string('comment', 'aca'), get_string('lastmodified').' ('.$course->student.')', get_string('lastmodified').' ('.$course->teacher.')', get_string('status'));

        require_once($CFG->libdir.'/tablelib.php');
        $table = new flexible_table('mod-aca-submissions');
                        
        $table->define_columns($tablecolumns);
        $table->define_headers($tableheaders);
        $table->define_baseurl($CFG->wwwroot.'/mod/aca/submissions.php?id='.$this->cm->id);
                
        $table->sortable(true);
        $table->collapsible(true);
        $table->initialbars(true);
        
        $table->column_suppress('picture');
        $table->column_suppress('fullname');
        
        $table->column_class('picture', 'picture');
        $table->column_class('fullname', 'fullname');
        $table->column_class('grade', 'grade');
        $table->column_class('comment', 'comment');
        $table->column_class('timemodified', 'timemodified');
        $table->column_class('timemarked', 'timemarked');
        $table->column_class('status', 'status');
        
        $table->set_attribute('cellspacing', '0');
        $table->set_attribute('id', 'attempts');
        $table->set_attribute('class', 'submissions');
        $table->set_attribute('width', '90%');
        $table->set_attribute('align', 'center');
            
        // Start working -- this is necessary as soon as the niceties are over
        $table->setup();

    /// Check to see if groups are being used in this assignment
        if ($groupmode = groupmode($course, $cm)) {   // Groups are being used
            $currentgroup = setup_and_print_groups($course, $groupmode, 'submissions.php?id='.$this->cm->id);
        } else {
            $currentgroup = false;
        }

    /// Get all teachers and students
        if ($currentgroup) {
            $users = get_group_users($currentgroup);
        } else {
            $users = get_course_users($course->id);
        }
            
        if (!$teacherattempts) {
            $teachers = get_course_teachers($course->id);
            if (!empty($teachers)) {
                $keys = array_keys($teachers);
            }
            foreach ($keys as $key) {
                unset($users[$key]);
            }
        }
        
        if (empty($users)) {
            print_heading(get_string('noattempts','aca'));
            return true;
        }

    /// Construct the SQL

        if ($where = $table->get_sql_where()) {
            $where .= ' AND ';
        }

        if ($sort = $table->get_sql_sort()) {
            $sort = ' ORDER BY '.$sort;
        }

        $select = 'SELECT u.id, u.id, u.firstname, u.lastname, u.picture, s.id AS submissionid, s.grade, s.comment, s.timemodified, s.timemarked, ((s.timemarked > 0) AND (s.timemarked >= s.timemodified)) AS status ';
        $sql = 'FROM '.$CFG->prefix.'user u '.
               'LEFT JOIN '.$CFG->prefix.'aca_submissions s ON u.id = s.userid AND s.acaid = '.$this->assignment->id.' '.
               'WHERE '.$where.'u.id IN ('.implode(',', array_keys($users)).') ';
    
        $table->pagesize($perpage, count($users));
        
        if($table->get_page_start() !== '' && $table->get_page_size() !== '') {
            $limit = " LIMIT ".$table->get_page_start().", ".$table->get_page_size(); 
            //$limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size());   
        }
        else {
            $limit = '';
        }
    
        ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
        $offset = $page * $perpage;
        
        $strupdate = get_string('update');
        $strgrade  = get_string('grade');
        $grademenu = make_grades_menu($this->assignment->grade);

        if (($ausers = get_records_sql($select.$sql.$sort.$limit)) !== false) {
            
            foreach ($ausers as $auser) {
            
            	//Benny            	
            	$course_id      = $course->id;
				$role_id        = get_field('role', 'id', 'shortname', 'student');
				$course_context = get_context_instance(CONTEXT_COURSE, $course_id);
				$isthere        = user_has_role_assignment($auser->id, $role_id, $course_context->id);
				
				if ($isthere):
            	
            		//echo "<br/><br/>--- break - $auser->id - $course->id ---<br/><br/>";
            	
            
                $picture = print_user_picture($auser->id, $course->id, $auser->picture, false, true);
                
                if (empty($auser->submissionid)) {
                    $auser->grade = -1; //no submission yet
                }
                    
                if (!empty($auser->submissionid)) {
                ///Prints student answer and student modified date
                ///attach file or print link to student answer, depending on the type of the assignment.
                ///Refer to print_student_answer in inherited classes.     
                    if ($auser->timemodified > 0) {            
                        $studentmodified = '<div id="ts'.$auser->id.'">'.$this->print_student_answer($auser->id).userdate($auser->timemodified).'</div>';
                    } else {
                        $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
                    }
                    
                    //PAJA added: create link to PD results window
                    $pdresults = '';
                    $pdresultsform = '';
                    if($this->check_tokens_created($this->assignment->id,$auser->id)) {
                        
                        if (count_records("aca_pd_similarity","acaid",$this->assignment->id,"id_pri",$auser->id)) {
                            $pdresults = link_to_popup_window($CFG->wwwroot.'//mod/aca/similarities.php?a='.$this->assignment->id.'&amp;user='.$auser->id,
                                                          'similarities',get_string('showsimilarity','aca'),600,800,get_string('popupwindow'),'none',true);
                            $pdresultsform = $this->print_similarities($this->assignment,$auser->id,1);
                        }        
                        else $pdresults = get_string('nosimilarity','aca');
                    }
                    else $pdresults = get_string('tokensnotexists','aca');
                    
                ///Print grade, dropdown or text
                    if ($auser->timemarked > 0) {
                        //PAJA added: link to PD results, button to test TV
                        $teachermodified = '<div id="tt'.$auser->id.'">'.$pdresults.'<br />'.$this->print_tv_test_button($auser->id).'<br />'.userdate($auser->timemarked).'</div>';
                        if ($quickgrade) {
                            $grade = '<div id="g'.$auser->id.'">'.choose_from_menu(make_grades_menu($this->assignment->grade), 
                            'menu['.$auser->id.']', $auser->grade, get_string('nograde'),'',-1,true,false,$tabindex++).'</div>';
                        } else {
                            $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
                        }

                    } else {
                        //PAJA added: link to PD results, button to test TV
                        $teachermodified = '<div id="tt'.$auser->id.'">'.$pdresults.'<br />'.$this->print_tv_test_button($auser->id).'</div>';
                        if ($quickgrade){                    
                            $grade = '<div id="g'.$auser->id.'">'.choose_from_menu(make_grades_menu($this->assignment->grade), 
                            'menu['.$auser->id.']', $auser->grade, get_string('nograde'),'',-1,true,false,$tabindex++).'</div>';
                        } else {
                            $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
                        }
                    }
                ///Print Comment
                    if ($quickgrade){
                        //PAJA added: prints PD results to comment form
                        $comment = '<div id="com'.$auser->id.'"><textarea tabindex="'.$tabindex++.'" name="comment['.$auser->id.']" id="comment['.$auser->id.']">'.($auser->comment).$pdresultsform.'</textarea></div>';
                    } else {
                        $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->comment),15).'</div>';
                    }
                } else {
                    $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
                    $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
                    $status          = '<div id="st'.$auser->id.'">&nbsp;</div>';
                    if ($quickgrade){   // allow editing
                        $grade = '<div id="g'.$auser->id.'">'.choose_from_menu(make_grades_menu($this->assignment->grade),
                                 'menu['.$auser->id.']', $auser->grade, get_string('nograde'),'',-1,true,false,$tabindex++).'</div>';
                    } else {
                        $grade = '<div id="g'.$auser->id.'">-</div>';
                    }
                    if ($quickgrade){
                        $comment = '<div id="com'.$auser->id.'"><textarea tabindex="'.$tabindex++.'" name="comment['.$auser->id.']" id="comment['.$auser->id.']">'.($auser->comment).'</textarea></div>';
                    } else {
                        $comment = '<div id="com'.$auser->id.'">&nbsp;</div>';
                    }
                }

                if ($auser->status === NULL) {
                    $auser->status = 0;
                }

                $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
                
                ///No more buttons, we use popups ;-).
                $button = link_to_popup_window ('/mod/aca/submissions.php?id='.$this->cm->id.'&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;offset='.$offset++, 
                                                'grade'.$auser->id, $buttontext, 500, 780, $buttontext, 'none', true, 'button'.$auser->id);

                $status  = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
                
                $row = array($picture, fullname($auser), $grade, $comment, $studentmodified, $teachermodified, $status);
                $table->add_data($row);
                
                //Benny
                endif;
            }
        }
        
        
        //PAJA added: print testing buttons
        $this->print_tv_testall_button();
        // print PD buttons if some PD is active
        if (get_records('aca_pd_active','acaid',$this->assignment->id)) {
            $this->print_makealltokens_button($this->assignment);
            $this->print_makesummary_button($this->assignment);
        }
        
        /// Print quickgrade form around the table
        if ($quickgrade){
            echo '<form action="submissions.php" name="fastg" method="post">';
            echo '<input type="hidden" name="id" value="'.$this->cm->id.'">';
            echo '<input type="hidden" name="mode" value="fastgrade">';
            echo '<input type="hidden" name="page" value="'.$page.'">';
        }
                
        $table->print_html();  /// Print the whole table

        if ($quickgrade){
            echo '<p align="center"><input type="submit" name="fastg" value="'.get_string('saveallfeedback', 'aca').'" /></p>';
            echo '</form>';
        }
        /// End of fast grading form
        
        /// Mini form for setting user preference
        echo '<br />';
        echo '<form name="options" action="submissions.php?id='.$this->cm->id.'" method="post">';
        echo '<input type="hidden" id="updatepref" name="updatepref" value="1" />';
        echo '<table id="optiontable" align="center">';
        echo '<tr align="right"><td>';
        echo '<label for="perpage">'.get_string('pagesize','aca').'</label>';
        echo ':</td>';
        echo '<td align="left">';
        echo '<input type="text" id="perpage" name="perpage" size="1" value="'.$perpage.'" />';
        helpbutton('pagesize', get_string('pagesize','aca'), 'aca');
        echo '</td></tr>';
        echo '<tr align="right">';
        echo '<td>';
        print_string('quickgrade','aca');
        echo ':</td>';
        echo '<td align="left">';
        if ($quickgrade){
            echo '<input type="checkbox" name="quickgrade" value="1" checked="checked" />';
        } else {
            echo '<input type="checkbox" name="quickgrade" value="1" />';
        }
        helpbutton('quickgrade', get_string('quickgrade', 'aca'), 'aca').'</p></div>';
        echo '</td></tr>';
        echo '<tr>';
        echo '<td colspan="2" align="right">';
        echo '<input type="submit" value="'.get_string('savepreferences').'" />';
        echo '</td></tr></table>';
        echo '</form>';
        ///End of mini form
        print_footer($this->course);
    }

    /*
     *  Display and process the submissions 
     */
    function process_feedback() {

        global $USER;

        if (!$feedback = data_submitted()) {      // No incoming data?
            return false;
        }

        ///For save and next, we need to know the userid to save, and the userid to go
        ///We use a new hidden field in the form, and set it to -1. If it's set, we use this
        ///as the userid to store
        if ((int)$feedback->saveuserid !== -1){
            $feedback->userid = $feedback->saveuserid;
        }

        if (!empty($feedback->cancel)) {          // User hit cancel button
            return false;
        }

        $newsubmission = $this->get_submission($feedback->userid, true);  // Get or make one

        $newsubmission->grade      = $feedback->grade;
        $newsubmission->comment    = $feedback->comment;
        $newsubmission->format     = $feedback->format;
        $newsubmission->teacher    = $USER->id;
        $newsubmission->mailed     = 0;       // Make sure mail goes out (again, even)
        $newsubmission->timemarked = time();

        if (empty($submission->timemodified)) {   // eg for offline assignments
            $newsubmission->timemodified = time();
        }

        if (! update_record('aca_submissions', $newsubmission)) {
            return false;
        }

        add_to_log($this->course->id, 'aca', 'update grades', 
                   'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id);
        
        return $newsubmission;

    }

    function get_submission($userid=0, $createnew=false) {
        global $USER;

        if (empty($userid)) {
            $userid = $USER->id;
        }

        $submission = get_record('aca_submissions', 'acaid', $this->assignment->id, 'userid', $userid);

        if ($submission || !$createnew) {
            return $submission;
        }
        $newsubmission = $this->prepare_new_submission($userid);
        if (!insert_record("aca_submissions", $newsubmission)) {
            error("Could not insert a new empty submission");
        }

        return get_record('aca_submissions', 'acaid', $this->assignment->id, 'userid', $userid);
    }
    
    /**
     * function to create new submission object
     **/
    //PAJA modify: removed data1, data2
    function prepare_new_submission($userid) {
        $submission = new Object;
        $submission->acaid        = $this->assignment->id;
        $submission->userid       = $userid;
        $submission->timecreated  = time();
        $submission->timemodified = $submission->timecreated;
        $submission->numfiles     = 0;
        $submission->grade        = -1;
        $submission->comment      = '';
        $submission->format       = 0;
        $submission->teacher      = 0;
        $submission->timemarked   = 0;
        $submission->mailed       = 0;
        return $submission;
    }

    function get_submissions($sort='', $dir='DESC') {
        /// Return all assignment submissions by ENROLLED students (even empty)
        global $CFG;

        if ($sort == "lastname" or $sort == "firstname") {
            $sort = "u.$sort $dir";
        } else if (empty($sort)) {
            $sort = "a.timemodified DESC";
        } else {
            $sort = "a.$sort $dir";
        }

        $select = "s.course = '$this->assignment->course' AND";
        $site = get_site();
        if ($this->assignment->course == $site->id) {
            $select = '';
        }   
        return get_records_sql("SELECT a.* 
                FROM {$CFG->prefix}aca_submissions a, 
                {$CFG->prefix}user_students s,
                {$CFG->prefix}user u
                WHERE a.userid = s.userid
                AND u.id = a.userid
                AND $select a.acaid = '$this->assignment->id' 
                ORDER BY $sort");
    }

    function count_real_submissions($groupid=0) {
        // Return all real assignment submissions by ENROLLED students (not empty ones)
        global $CFG;
        //$contextid = get_context_instance(CONTEXT_COURSE, $this->assignment->id);

        if ($groupid) {     /// How many in a particular group?
            return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
                    FROM {$CFG->prefix}aca_submissions a,
                    {$CFG->prefix}groups_members g
                    WHERE a.acaid = {$this->assignment->id} 
                    AND a.timemodified > 0
                    AND g.groupid = '$groupid' 
                    AND a.userid = g.userid ");
        } else {
            //$select = "c.contextid = '{$contextid->id}' AND";
            $select = '';
            if ($this->assignment->course == SITEID) {
                $select = '';
            }
            return count_records_sql("SELECT COUNT(*)
                    FROM {$CFG->prefix}aca_submissions a, 
                    {$CFG->prefix}user s, {$CFG->prefix}role_assignments c 
                    WHERE a.acaid = '{$this->assignment->id}' 
                    AND a.timemodified > 0
                    AND $select a.userid = s.id AND (s.id = c.userid AND c.roleid = '5')");
                    
            /*return count_records_sql("SELECT COUNT(*)
                    FROM {$CFG->prefix}aca_submissions a, 
                    {$CFG->prefix}user_students ssssssssssssssssssssssss
                    WHERE a.acaid = '{$this->assignment->id}' 
                    AND a.timemodified > 0
                    AND $select a.userid = s.userid ");*/
        } 
    }
    
    function email_teachers($submission) {
        /// Alerts teachers by email of new or changed assignments that need grading

        global $CFG;

        if (empty($this->assignment->emailteachers)) {          // No need to do anything
            return;
        }

        $user = get_record('user', 'id', $submission->userid);

        if (groupmode($this->course, $this->cm) == SEPARATEGROUPS) {   // Separate groups are being used
            if (!$group = user_group($this->course->id, $user->id)) {             // Try to find a group
                $group->id = 0;                                             // Not in a group, never mind
            }
            $teachers = get_group_teachers($this->course->id, $group->id);        // Works even if not in group
        } else {
            $teachers = get_course_teachers($this->course->id);
        }

        if ($teachers) {

            $strassignments = get_string('modulenameplural', 'aca');
            $strassignment  = get_string('modulename', 'aca');
            $strsubmitted  = get_string('submitted', 'aca');

            foreach ($teachers as $teacher) {
                unset($info);
                $info->username = fullname($user);
                $info->assignment = format_string($this->assignment->name,true);
                $info->url = $CFG->wwwroot.'/mod/aca/submissions.php?id='.$this->cm->id;

                $postsubject = $strsubmitted.': '.$info->username.' -> '.$this->assignment->name;
                $posttext = $this->email_teachers_text($info);
                $posthtml = ($teacher->mailformat == 1) ? $this->email_teachers_html($info) : '';

                @email_to_user($teacher, $user, $postsubject, $posttext, $posthtml);  // If it fails, oh well, too bad.
            }
        }
    }
    
    function email_teachers_text($info) {
        $posttext  = $this->course->shortname.' -> '.$this->strassignments.' -> '.
                     format_string($this->assignment->name, true)."\n";
        $posttext .= '---------------------------------------------------------------------'."\n";
        $posttext .= get_string("emailteachermail", "aca", $info)."\n";
        $posttext .= '---------------------------------------------------------------------'."\n";
        return $posttext;
    }
    
    //PAJA modify 21.4.2006 18:01:40
    function email_teachers_html($info) {
        global $CFG;
        $posthtml  = '<p><font face="sans-serif">'.
                     '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$this->course->id.'">'.$this->course->shortname.'</a> ->'.
                     '<a href="'.$CFG->wwwroot.'/mod/aca/index.php?id='.$this->course->id.'">'.$this->strassignments.'</a> ->'.
                     '<a href="'.$CFG->wwwroot.'/mod/aca/view.php?id='.$this->cm->id.'">'.format_string($this->assignment->name,true).'</a></font></p>';
        $posthtml .= '<hr /><font face="sans-serif">';
        $posthtml .= '<p>'.get_string('emailteachermailhtml', 'aca', $info).'</p>';
        $posthtml .= '</font><hr />';
        return $posthtml;
    }
    
    /**
     * get sourcefiles in details.php form
     * if new assigment return '' (source dir must be free)
     **/
    function get_source_files($form) {
        global $USER, $course;
        // user must be a teacher
        if ($form->instance != '' && isteacher($course->id, $USER->id)) {
            $this->course->id = $form->course;
            $this->assignment->id = $form->instance;
            $this->print_user_files($USER->id,false,1);
        }
    }
    
    //PAJA modify: add source boolean flag
    function print_user_files($userid=0, $return=false,$source=0) {
        global $CFG, $USER;
    
        if (!$userid) {
            if (!isloggedin()) {
                return '';
            }
            $userid = $USER->id;
        }
    
        $filearea = $this->file_area_name($userid,$source);
                
        $output = '';
    
        if ($basedir = $this->file_area($userid,$source)) {
            if ($files = get_directory_list($basedir)) {
                
                foreach ($files as $key => $file) {
                    require_once($CFG->libdir.'/filelib.php');
                    
                    $icon = mimeinfo('icon', $file);
                    
                    if ($CFG->slasharguments) {
                        $ffurl = "$CFG->wwwroot/file.php/$filearea/$file";
                    } else {
                        $ffurl = "$CFG->wwwroot/file.php?file=/$filearea/$file";
                    }
                
                    $output .= '<img align="middle" src="'.$CFG->pixpath.'/f/'.$icon.'" height="16" width="16" alt="'.$icon.'" />'.
                            '<a href="'.$ffurl.'" >'.$file.'</a><br />';
                }
            }
        }

        $output = '<div class="files">'.$output.'</div>';

        if ($return) {
            return $output;
        }
        echo $output;
    }
    
    //PAJA modify: add source boolean flag
    function count_user_files($userid,$source=0) {
        global $CFG;

        $filearea = $this->file_area_name($userid,$source);

        if ($basedir = $this->file_area($userid,$source)) {
            if ($files = get_directory_list($basedir)) {
                return count($files);
            }
        }
        return 0;
    }

    //PAJA modify: add source boolean flag and source functionality
    function file_area_name($userid,$source=0) {
    //  Creates a directory file name, suitable for make_upload_directory()
        global $CFG;
        // if source, then return sourcefile area (dir source, not userid)
        if ($source) {
            return $this->course->id.'/'.$CFG->moddata.'/aca/'.$this->assignment->id.'/source';
        }
        else return $this->course->id.'/'.$CFG->moddata.'/aca/'.$this->assignment->id.'/'.$userid;
    }
    
    //PAJA modify: add source boolean flag
    function file_area($userid,$source=0) {
        return make_upload_directory( $this->file_area_name($userid,$source) );
    }

    function isopen() {
        $time = time();
        if ($this->assignment->preventlate && $this->assignment->timedue) {
            return ($this->assignment->timeavailable <= $time && $time <= $this->assignment->timedue);
        } else {
            return ($this->assignment->timeavailable <= $time);
        }
    }

    function user_outline($user) {
        if ($submission = $this->get_submission($user->id)) {

            $result->info = get_string('grade').': '.$this->display_grade($submission->grade);
            $result->time = $submission->timemodified;
            return $result;
        }
        return NULL;
    }
    
    function user_complete($user) {
        if ($submission = $this->get_submission($user->id)) {
            if ($basedir = $this->file_area($user->id)) {
                if ($files = get_directory_list($basedir)) {
                    $countfiles = count($files)." ".get_string("uploadedfiles", "aca");
                    foreach ($files as $file) {
                        $countfiles .= "; $file";
                    }
                }
            }
    
            print_simple_box_start();
            echo get_string("lastmodified").": ";
            echo userdate($submission->timemodified);
            echo $this->display_lateness($submission->timemodified);
    
            $this->print_user_files($user->id);
    
            echo '<br />';
    
            if (empty($submission->timemarked)) {
                print_string("notgradedyet", "aca");
            } else {
                $this->view_feedback($submission);
            }
    
            print_simple_box_end();
    
        } else {
            print_string("notsubmittedyet", "aca");
        }
    }

    function display_lateness($timesubmitted) {
        if (!$this->assignment->timedue) {
            return '';
        }
        $time = $this->assignment->timedue - $timesubmitted;
        if ($time < 0) {
            $timetext = get_string('late', 'assignment', format_time($time));
            return ' (<span class="late">'.$timetext.'</span>)';
        } else {
            $timetext = get_string('early', 'assignment', format_time($time));
            return ' (<span class="early">'.$timetext.'</span>)';
        }
    }

    /* THERE ARE NEW FUNCTIONS FOR TEST VECTORS */
    
    /** 
     * get counts of active tvs and sum of grades for this vectors
     * @param int $tvid id of test vector
     * @param int $acaid id of ac assigment
     * @return object
     **/    
    function get_tv_counts($tvid,$acaid) {
        global $CFG;
        
        $sql = "SELECT count( id ) AS count, sum( grade ) AS gradesum
                    FROM {$CFG->prefix}aca_tv_active
                    WHERE tvid = $tvid
                    AND acaid = $acaid
                    GROUP BY tvid";
        return get_record_sql($sql);
    }
    
    /** 
     * prints summary in assig. setup page (details.php->common.html)
     * @param object $assignment
     * @return echoed by print_table()
     **/
    function print_tvs_summary($assignment) {
        global $CFG;
        
        $acaid = $assignment->id;
        $langtype = $assignment->langtype;
        
        // get information about tvs
        if ($summary = get_records('aca_tvs','langtype',$langtype)) {
        
            echo '<table align="center"><tr><td>';
            print_single_button('view.php?id='.$this->cm->id,array('test'=>'1'),get_string('runtest','aca'),'post');
            echo '</td></tr></table>';
            
            // create table
            $table->head = array(
                get_string('testvectorname','aca'),
                get_string('testvectorsettings','aca'),
                get_string('testvectorcount','aca'),
                get_string('testvectorgradecount','aca'),
                get_string('testvectoraddnew','aca')
            );
            
            $sumvectors = 0;
            $sumgrades = 0;
            foreach ($summary as $id=>$tv) {
                if (!$cnts = $this->get_tv_counts($tv->id,$acaid)) {
                    $cnts->count = 0;
                    $cnts->gradesum = 0;
                }
                $sumvectors += $cnts->count;
                $sumgrades += $cnts->gradesum;
                
                $table->data[$id][] = get_string('name'.$tv->name,'aca');
                $table->data[$id][] = link_to_popup_window($CFG->wwwroot.'//mod/aca/testvectors.php?id='.$this->cm->id.'&amp;a='.$acaid.'&amp;tv='.$tv->id.'&amp;mode=edit',
                                                                 'testvector',get_string('testvectorsettings','aca'),600,800,get_string('popupwindow'),'none',true);
                $table->data[$id][] = '<span id="count'.$tv->id.'">'.$cnts->count.'</span>';
                $table->data[$id][] = '<span id="grades'.$tv->id.'">'.$cnts->gradesum.'</span>';
                $table->data[$id][] = button_to_popup_window('/mod/aca/testvectors.php?id='.$this->cm->id.'&amp;a='.$acaid.'&amp;tv='.$tv->id.'&amp;mode=add',
                                                                 'testvector',get_string('add'),600,800,get_string('popupwindow'),'none',true);
            }
            // prints some summaries of table - last row of table
            $table->data[]=array('<b>'.get_string('summaries','aca').'</b>','&nbsp;','<span id="sumgrades">'.$sumvectors.'</span>','<span id="sumgvectors">'.$sumgrades.'</span>','&nbsp;');
            $table->align=array('left','left','right','right','right');
            
            print_table($table);
        }
    }
    
    /** 
     * function to make new test vector with default values
     * @return object new test vector
     **/
    function get_new_tv($tv) {
        $vec = new Object;
        $vec->tvid = $tv->id;
        $vec->acaid = $this->assignment->id;
        $vec->test_opt = 0;
        $vec->test_val = '';
        $vec->in_opt = 0;
        $vec->in_string = '';
        $vec->in_text = '';
        $vec->grade = -1;
        $vec->timemodified = time();
        return $vec;
    }
    
    /** 
     * function to make new result of test vector
     * @return object new result of test vector
     **/
    function new_tv_result($tv,$submission) {
        $vec = new Object;
        $vec->activetvid = $tv->id;
        $vec->acaid = $this->assignment->id;
        $vec->submissionid = ($submission != 0) ? $submission : 0;
        $vec->indata = '';
        $vec->teacher_out = '';
        $vec->student_out = '';
        $vec->result = 0;
        $vec->description = '';
        $vec->timemodified = time();
        return $vec;
    }
    
    /**
     * Top level function for TV setting and viewing results of test vectors
     * @param string $mode type of action
     * @param object $tv aca_tvs DB object
     * @param int $submission submission ID or 0 if only teacher test
     * @return print data to testvectors.php page
     **/
    function testvectors($mode,$tv,$submission=0) {
        global $CFG;
        // select heading
        if ($tv) {
            $heading = get_string('type'.$tv->langtype,'aca').' - '.get_string('name'.$tv->name,'aca');
            print_header(get_string('testvectorsettings','aca'));
        }
        if ($submission) {
            $heading = get_string('testresults','aca');
            print_header(get_string('testresults','aca'));
        }
        print_heading_block($heading);
        if ($tv) print_simple_box(get_string('description'.$tv->name,'aca'),'center');
        
        //called if we testing one student's submission
        $test = optional_param('test',0);
        if ($test) {
            if ($submission!=0) {
                $back = $_SERVER["HTTP_REFERER"];
                $test = $this->tv_testing($this->assignment,$submission);
                // what we need to do after testing
                $mode = 'view';
                echo '<br /><center>' . "\n";
                echo '<script type="text/javascript">' . "\n";
                echo '<!--' . "\n";
                echo "document.write('<form>');\n";
                echo "document.write('<input type=\"button\" onclick=\"window.opener.location.href= \'$back\';self.close();\" value=\"".get_string("closewindow")."\" />');\n";
                echo "document.write('<\/form>');\n";
                echo '-->' . "\n";
                echo '</script>' . "\n";
                echo '<noscript>' . "\n";
                print_string('closewindow');
                echo '</noscript>' . "\n";
                echo '</center><br />' . "\n";
            }
            else notify(get_string('testerror','aca'));
        }
        
        // save new test vector data
        $newvector = optional_param('newvector',false);
        if ($newvector == 1) {
            $new = $this->get_new_tv($tv);
            $items = get_object_vars($new);
            // get all vars to new item
            foreach ($items as $key=>$val) {
                if ($str = optional_param($key,false)) $new->$key=$str;
            }
            if (!insert_record('aca_tv_active',$new)) notify('Not created');
            if ($mode != 'editend') {
                echo '<script type="text/javascript">'."\n<!--\n";
                // try to reload main window
                echo 'window.opener.location.replace(window.opener.location.href);';
                echo "\n-->\n</script>";
            }
        }
        
        //switch of mode where we are
        
        switch ($mode) {
            case 'editend':                         // popup window closing
                if (!$newvector) $this->process_tvs($tv); // saves all changes
                echo '<script type="text/javascript">'."\n<!--\n";
                // try to reload main window
                echo 'window.opener.location.replace(window.opener.location.href);';
                echo "\n-->\n</script>";
                close_window();
                break;
                
            case 'view':                           // view test methods with results
                //PAJA todo this function
                $this->display_tv_results($this->assignment,$submission,NULL,$test);
                break;

            case 'del': if ($tv) {                        // deletes test method
                    $seltvid = optional_param('seltvid');
                    if ($deltv = get_record('aca_tv_active','id',$seltvid)) {
                        if (delete_records('aca_tv_results','activetvid',$seltvid)) {
                            notify('Test results deleted');
                            if(delete_records('aca_tv_active','id',$seltvid))
                                notify(get_string('deleted'));
                            else notify('Can\'t delete test vector.');
                        }
                        else notify('Can\'t delete test results.');
                    }
                    else notify('Invalid id. Nothing deleted.');
                    // page variables and form with continue button
                    echo '<table align="center"><tr><td>
                    <form action="testvectors.php" method="post">
                        <input type="hidden" name="id" value="'.$this->cm->id.'">
                        <input type="hidden" name="tv" value="'.$tv->id.'">
                        <input type="hidden" name="mode" value="edit">
                        <input type="submit" name="continue" value="'.get_string('continue').'">
                    </form>
                    </td></table></table>';
                }
                else error('Cannot delete');
                break;
            
            case 'edit': if ($tv) {                          // editing vectors with same id
                    $active = get_records_select('aca_tv_active','acaid = '.$this->assignment->id.' AND tvid = '.$tv->id,'id');
                    
                    // loads template array defined in each lang. submodule
                    $tvtype = $tv->langtype.'_tv_setting';
                    if (!method_exists($this,$tvtype)) error("Sablot for this test method not defined.");
                    
                    // begin FORM
                    echo '<form name="tvs" action="testvectors.php" method="post">';
                    
                    // iterate through all active vectors
                    if ($active && sizeof($active)) {
                        
                        // last tested sumbissions (result table) - check if tv was tested
                        $sql = "SELECT activetvid as atv,max(timemodified) as time FROM {$CFG->prefix}aca_tv_results
                                    WHERE acaid = ".$this->assignment->id."
                                    GROUP BY atv";
                        $tested = array();
                        if ($tested = get_records_sql($sql)) {
                            $temp = array();
                            // flatten - only in array $activetvid->$time
                            foreach ($tested as $key=>$val) {
                                $temp[$val->atv]=$val->time;
                            }
                            $tested = $temp;
                            unset($temp);
                        }
                        
                        // HEADINGS OF TABLE
                        $table->head['id'] = 'id';  // get start standard heading
                        
                        // get additional heading from sablot function
                        $table->head = array_merge($table->head,$this->$tvtype($tv->id,$tv,'head'));
                        // end of standard heading ...
                        $table->head['grade']= get_string('grade');
                        $table->head['atest']= get_string('alreadytested','aca');
                        $table->head['actions']= get_string('actions','aca');
                        
                        // TABLE ROWS DATA
                        // print form data from sablots
                        foreach ($active as $row=>$data) {
                            // standard data start
                            $table->data[$row]['id']=$row;
                            
                            // additional data from sablots
                            $table->data[$row] = array_merge($table->data[$row],$this->$tvtype($tv->id,$data));
                            
                            // standard data end
                            $table->data[$row]['grade']=choose_from_menu(range(0,$this->assignment->grade), "grade[$data->id]", $data->grade, get_string('nograde'), '', -1,true);
                            $table->data[$row]['atest']=isset($tested[$data->id])? get_string('yes').'<br />('.userdate($tested[$data->id]).')' : get_string('no');
                            $table->data[$row]['actions']=$this->print_copy_tv_button($data->id).'&nbsp;'.$this->print_del_tv_button($data->id);
                        }
                        print_table($table);
                        
                    }
                    else print_simple_box(get_string('novectorsyet','aca'),'center');
                    
                    echo '<table align="center"><tr><td>';
                    // vector operations field
                    echo '<input type="hidden" name="seltvid" value="">';
                    // page variables
                    echo '<input type="hidden" name="id" value="'.$this->cm->id.'">
                          <input type="hidden" name="tv" value="'.$tv->id.'">';
                    // submit & addnew button
                    echo '<input type="submit" value="'.get_string('savechanges').'" onclick="document.tvs.mode.value=\'editend\';">
                          <input type="submit" value="'.get_string('add').'" onclick="document.tvs.mode.value=\'add\';">';
                    // mode field
                    echo '<input type="hidden" name="mode" value="edit">';
                    echo '</td></tr></table>';
                    
                    echo '</form>';
                    
                }
                else error('Cannot edit different types of test vectors');
                break;

                case 'add': if ($tv) {                          // adding new test vector tvid
                    // copy of this vector
                    $seltvid = optional_param('seltvid','');

                    // loads template array defined in each lang. submodule
                    $tvtype = $tv->langtype.'_tv_setting';
                    if (!method_exists($this,$tvtype)) error("Sablot for this test vector not defined. See at submodule.");
                    
                    if ($seltvid !='') {
                        $new_vector = get_record('aca_tv_active','id',$seltvid);
                        if (!$new_vector) notice('Invalid copy of vector');
                    }
                    // create if not copy
                    if (!isset($new_vector)) {
                        $new_vector = $this->get_new_tv($tv);
                    }
                    
                    echo '<form name="tvs" action="testvectors.php" method="post">';
                        
                    // get additional heading
                    $table->head = $this->$tvtype($tv->id,$tv,'head',0);
                    // get end standard heading
                    $table->head['grade']= get_string('grade');
                    
                    // print form data from sablots
                    $row = 1;
                    // additional data from sablots
                    $table->data[$row] = $this->$tvtype($tv->id,$new_vector,'form',0);
                    
                    // standard data end
                    $table->data[$row]['grade']=choose_from_menu(range(0,$this->assignment->grade), "grade", $new_vector->grade, get_string('nograde'), '', -1,true);
                    print_table($table);
                    
                    echo '<table align="center"><tr><td>';
                    // newfile atribute
                    echo '<input type="hidden" name="newvector" value="1">';
                    // page variables
                    echo '<input type="hidden" name="id" value="'.$this->cm->id.'">
                          <input type="hidden" name="tv" value="'.$tv->id.'">';
                    // submit&edit , submit&close buttons
                    echo '<input type="submit" value="'.get_string('saveedit','aca').'" onclick="document.tvs.mode.value=\'edit\';">
                          <input type="submit" value="'.get_string('saveclose','aca').'" onclick="document.tvs.mode.value=\'editend\';">';
                    // mode field
                    echo '<input type="hidden" name="mode" value="edit">';
                    echo '</td></tr></table>';
                    
                    echo '</form>';
                    
                }
                else error('Cannot add vector without type');
                break;            
            
            default:
                echo "Something seriously is wrong!!";
                break;                    
        }
        
        print_footer('none');
    }
    
    /**
     * function to print button to copy test vector in testvectors.php
     * @return string to echo
     **/
    function print_copy_tv_button($tvid) {
        $onclick = "document.tvs.mode.value='add';";
        $onclick .= "document.tvs.seltvid.value='$tvid';";
        $str = '<input type="submit" onclick="'.$onclick.'" name="copy" value="'.get_string('copyvector','aca').'">';
        return $str;
    }
    
    /**
     * function to print button to delete test vector in testvectors.php
     * @return string to echo
     **/
    function print_del_tv_button($tvid) {
        $onclick = "document.tvs.mode.value='del';";
        $onclick .= "document.tvs.seltvid.value='$tvid';";
        $onclick .= "return confirm('".get_string('confirmdelete','aca')."');";
        $str = '<input type="submit" onclick="'.$onclick.'" name="delete" value="'.get_string('deletevector','aca').'">';
        return $str;
    }
    
    /**
     * function to save test vector changes
     * iterate thgough _POST vars arrays with TVs settings
     * @param object $tv - active_tv DB row
     * @return none (only updates the DB)
     **/
    function process_tvs($tv) {
        $new = $this->get_new_tv($tv);
        $items = get_object_vars($new);
        //create new objects
        foreach ($_POST['grade'] as $key=>$val) {
            $data[$key]=$this->get_new_tv($tv);
            $data[$key]->id=$key;
        }
        // get all vars to new item
        foreach ($items as $key=>$val) {
            if (isset($_POST[$key]) && sizeof($_POST[$key])) {
                foreach ($_POST[$key] as $id=>$postval) {
                    $data[$id]->$key = $postval;
                }
            }
        }
        
        foreach ($data as $key=>$val) {
            if (!update_record('aca_tv_active',$val)) notify("$key not created");
        }
    }
    
    /**
     * function to display table of test result
     * it called by testvectors.php in view mode
     * calls garding_module function to grade test vectors
     * @param $assignment
     * @param $submission - 0 if teacher test
     * @param $testdata - used only in teachetest
     * @param $write - write grade to DB or only view it
     **/
    function display_tv_results($assignment,$submission=0,$testdata=NULL,$write=0) {
        global $USER,$CFG,$ACACFG,$course;
        
        $showall = (isteacher($course->id, $USER->id) || ($assignment->showtest==1));
        
        $data = false;
        // only for teachers
        if (isteacher($course->id, $USER->id) && $testdata!=NULL && sizeof($testdata)) {
            $data = $testdata;
            unset($testdata);
        }
        //student must have submission
        elseif($submission!=0) {
            $data = get_records_select('aca_tv_results',"acaid = '$assignment->id' AND submissionid = '$submission'",'activetvid');
        }
        // show table
        if ($data && sizeof($data)) {
            $table->head[] = get_string('testoutid','aca');
            $table->head[] = get_string('testoutin','aca');
            $table->head[] = get_string('testoutout','aca');
            $table->head[] = get_string('testoutgood','aca');
            $table->head[] = get_string('testoutmaxgrade','aca');
            $table->head[] = get_string('testoutrecountgrade','aca');
            $table->head[] = get_string('testoutgrade','aca');
            
            // call grading module - modify the result data
            $gradearr = $this->grading_module($data,$assignment,$submission,$write);
            
            $table->align = array('right','left','left','left','right','right','right');
            
            $sumg = 0;
            foreach ($data as $row=>$tv) {
                if ($showall || ($tv->result==0)) {
                    $table->data[$row][] = $tv->activetvid;
                    $table->data[$row][] = $tv->indata;

                    // STUDENT OUT (string or link to result)
                    if (strlen($tv->student_out) < $ACACFG->maxstrreslenght || $submission == 0) $table->data[$row][] = htmlspecialchars($tv->student_out);
                    else $table->data[$row][] = link_to_popup_window($CFG->wwwroot.'//mod/aca/descriptions.php?id='.$this->cm->id.'&amp;a='.$assignment->id.'&amp;trid='.$tv->id.'&amp;res=s',
                                             'differences',get_string('descriptions','aca'),600,800,get_string('popupwindow'),'none',true);
                    // TEACHER OUT (string or link to result)
                    if (strlen($tv->teacher_out) < $ACACFG->maxstrreslenght || $submission == 0) $table->data[$row][] = htmlspecialchars($tv->teacher_out);
                    else $table->data[$row][] = link_to_popup_window($CFG->wwwroot.'//mod/aca/descriptions.php?id='.$this->cm->id.'&amp;a='.$assignment->id.'&amp;trid='.$tv->id.'&amp;res=t',
                                             'differences',get_string('descriptions','aca'),600,800,get_string('popupwindow'),'none',true);

                    $table->data[$row][] = $gradearr[$tv->activetvid]['vector'];
                    $table->data[$row][] = $gradearr[$tv->activetvid]['recount'];
                    if ($submission ==0)
                        $table->data[$row][] = $gradearr[$tv->activetvid]['current'];
                    else {
                        $link = link_to_popup_window($CFG->wwwroot.'//mod/aca/descriptions.php?id='.$this->cm->id.'&amp;a='.$assignment->id.'&amp;trid='.$tv->id,
                                                    'differences',get_string('descriptions','aca'),600,800,get_string('popupwindow'),'none',true);
                        $table->data[$row][] = $gradearr[$tv->activetvid]['current'].'<br />'.$link;
                    };
                }
                $sumg += $gradearr[$tv->activetvid]['current'];
            }
            
            if (sizeof($table->data) && $assignment->showtest!=0) {
                print_table($table);
                print_simple_box(get_string('getgrades','aca').": ".round($sumg)."/$assignment->grade",'center');
            }
        }
        else notify(get_string('notestdata','aca'));
    }
    
    /**
     * function to grade submission according to test vectors results and selected grading settings
     * @param $results - array of test results (from display_tv_results func.)
     * @param object $assignment
     * @param int $submission - submission ID where grade write to (0 if testing only)
     * @param int $write - write to DB or not
     **/
    function grading_module(&$results,$assignment,$submission,$write=0) {
        global $USER, $CFG;
        
        if ($grades = get_records("aca_tv_active","acaid",$assignment->id));
        else error('Cant\'t get grades for this assignment');
        
        $insert_val = false;
        $ret = array();
        
        if (sizeof($results)) {
            //sum of maxium possible grades
            $summg = 0;
            foreach ($grades as $key=>$val) {
                $summg += $val->grade;
                $ret[$key]['vector'] = $val->grade;
                $ret[$key]['tvid'] = $val->tvid;
            }
            
            //sum of actual grades
            $sumg = 0;
            foreach ($results as $val) $sumg += ($val->result == 1)? $grades[$val->activetvid]->grade : 0;
            
            //switch of grading options
            switch ($assignment->gradetype) {
                case 0: {   //manually
                    foreach ($results as $val) {
                        $key = $val->activetvid;
                        $ret[$key]['recount'] = $grades[$key]->grade;
                        $gr = ($val->result == 1)? $ret[$key]['recount'] : 0;
                        $ret[$key]['current'] = $gr;
                    }
                    $insert_val = -1;
                }
                break;
                case 1: {   //raw grades
                    // more then maximal
                    if ($summg > $assignment->grade) {
                        switch ($assignment->grademax) {
                            case 0: {   //weight
                                $factor = $assignment->grade/$summg;
                                $sum = 0;
                                foreach ($results as $val) {
                                    $key = $val->activetvid;
                                    $ret[$key]['recount'] = $grades[$key]->grade*$factor;
                                    $gr = ($val->result == 1)? $ret[$key]['recount'] : 0;
                                    $ret[$key]['current'] = $gr;
                                    $sum += $gr;
                                }
                                $insert_val = round($sum);
                            }
                            break;
                            case 1: {   //random
                                if (sizeof($results) < $assignment->graderandval) error('Invalid number of test vectors.');
                                $per_one = $assignment->grade/$assignment->graderandval;
                                
                                $sel = sizeof($results);
                                
                                // if there is more results then randval, we must delete some
                                while ($sel > $assignment->graderandval) {
                                    foreach ($results as $val) {
                                        $key = $val->activetvid;
                                        // if rand, then delete result from DB and data
                                        if (rand(0,1) == 1) {
                                            $sel--;
                                            if ($submission == 0) unset($results[$key]);
                                            else unset($results[$val->id]);
                                            if ($write) delete_records('aca_tv_results','id',$val->id);
                                            if ($sel == $assignment->graderandval) break(2);
                                        }
                                    }
                                }
                                
                                // count grades
                                $sum = 0;
                                foreach ($results as $val) {
                                    $key = $val->activetvid;
                                    $ret[$key]['recount'] = $per_one;
                                    $gr = ($val->result == 1)? $ret[$key]['recount'] : 0;
                                    $ret[$key]['current'] = $gr;
                                    $sum += $gr;
                                }
                                $insert_val = round($sum);
                            }
                            break;
                        }
                    }
                    // less then maximal
                    elseif ($summg < $assignment->grade) {
                        switch ($assignment->grademin) {
                            case 0: {   //weight
                               $factor = $assignment->grade/$summg;
                                $sum = 0;
                                foreach ($results as $val) {
                                    $key = $val->activetvid;
                                    $ret[$key]['recount'] = $grades[$key]->grade*$factor;
                                    $gr = ($val->result == 1)? $ret[$key]['recount'] : 0;
                                    $ret[$key]['current'] = $gr;
                                    $sum += $gr;
                                }
                                $insert_val = round($sum);
                            }
                            break;
                        }
                    }
                    else $retval = $sumg;
                }
                break;
                case 2: {   //weight function
                    $factor = $assignment->grade/$summg;
                    $sum = 0;
                    foreach ($results as $val) {
                        $key = $val->activetvid;
                        $ret[$key]['recount'] = $grades[$key]->grade*$factor;
                        $gr = ($val->result == 1)? $ret[$key]['recount'] : 0;
                        $ret[$key]['current'] = $gr;
                        $sum += $gr;
                    }
                    $insert_val = round($sum);
                }
                break;
                case 3: {   //uniform grades
                    $per_one = $assignment->grade/sizeof($grades);
                    $sum = 0;
                    foreach ($results as $val) {
                        $key = $val->activetvid;
                        $ret[$key]['recount'] = $per_one;
                        $gr = ($val->result == 1)? $ret[$key]['recount'] : 0;
                        $ret[$key]['current'] = $gr;
                        $sum += $gr;
                    }
                    $insert_val = round($sum);
                }
                break;
            }
        }
        
        // writing to DB
        $contextid = get_context_instance(CONTEXT_COURSE, $this->course->id);
        if ($write && $submission) {
            $upd->id = $submission;
            //$upd->teacher = get_field("users", "userid", array("foo" => "bar", "foo" => "bar"), array("foo" => "bar", "foo" => "bar"));
            $upd->teacher = get_field("role_assignments", "userid", "roleid", 3, "contextid", $contextid->id);
            $upd->timemarked = time();
            $upd->grade = $insert_val;
            if (!$res = update_record('aca_submissions',$upd)) notify("Can't autograde");
        }

        if (sizeof($ret)) return $ret;
        else return false;
    }
    
    /**
     * main function to test processing one submission (all active tests)
     * iterates through all testing methods for current assignment
     * calls specific languaget test function for test vectors
     * @param object $assignment
     * @param int $submission - 0 if teacher testing
     * @param int $notify - notify errors
     * @return boolean (if we can do the tests)
     **/
    function tv_testing($assignment,$submission=0,$notify=1) {
        global $USER;
        global $course;
        
        $pre_test = true;
        
        //pre_test_checking
        if ($submission != 0) $pre_test = get_field('aca_submissions','numfiles','id',$submission);
        $pre_test &= ($assignment->sourcefile != '');
        
        if ($pre_test) {
        
            // test function name
            $fname = $assignment->langtype.'_tv_testing';
            
           
            // only for teachers
            if (isteacher($course->id, $USER->id) && $submission == 0) {
            
                $testdata = array();
                if ($tv = get_records('aca_tv_active','acaid',$assignment->id,'id')) {
                    foreach ($tv as $val) {
                        $testdata[$val->id] = $this->$fname($val);
                    }
                }
                return $testdata;
            }
            // students - must have submission
            elseif ($submission!=0) {
                //get active vectors for this assignment
                if ($tv = get_records('aca_tv_active','acaid',$assignment->id,'id')) {
                    foreach ($tv as $val) $this->$fname($val,$submission);
                }
            }
            else error('Ivalid submission');
        }
        elseif($notify) notify(get_string('missingfiles','aca'));
        return $pre_test;
    }
    
    /**
     * function to process testing for each submissions in one assignment
     * testing is called only if submission is active (uploaded files)
     * all test data adre stored to DB 
     * grading module is called for all tests with results
     **/
    function process_test_all($acaid) {
        //if this aca exists
        if ($acaid == $this->assignment->id) {
            //get all submissions
            $process = false;
            if ($sms = get_records('aca_submissions','acaid',$acaid)) {
                foreach ($sms as $val) {
                    $test_res[$val->id] = $this->tv_testing($this->assignment,$val->id,0);
                    $process |= $test_res[$val->id];
                }
            }
            // if is submission with correct test
            if ($process) {
                if ($data = get_records_select('aca_tv_results',"acaid = '$acaid'",'submissionid,activetvid')) {
                    $lastsmid = 0;
                    $first = true;
                    foreach ($data as $key=>$val) {
                        if ($first) {
                            $lastsmid = $val->submissionid;
                            $first = false;
                        }
                        if ($lastsmid != $val->submissionid) {
                            $this->grading_module($sub_arr,$this->assignment,$lastsmid,$test_res[$lastsmid]);
                            unset($sub_arr);
                            $lastsmid = $val->submissionid;
                        }
                        $sub_arr[$key]=$val;
                    }
                    // process last buffered smid
                    if (sizeof($sub_arr)) {
                        $this->grading_module($sub_arr,$this->assignment,$lastsmid,$test_res[$lastsmid]);
                    }
                }
            }
        }
        else notify('Bad assignment specified');
    }
    
    /**
     * function to view description about one test (field description from aca_tv_results)
     * called by descriptions.php
     * @param int $trid - active test result ID
     * @param char $res - type of result (description, teacher, student)
     **/
    function descriptions($trid,$res) {
        $heading = get_string('descriptions','aca');
        print_header(get_string('descriptions','aca'));

        print_heading_block($heading);
        
        $result = false;
        // switch what we need to see
        switch ($res) {
            case ''  : {
                    $diffs = get_field('aca_tv_results','description','id',$trid);
                    if ($diffs != '') {
                        $buffer = explode("\n",$diffs);
                    }
                    else $buffer = $diffs;
                    // get readable output of diff
                    $result = $this->showdiff($buffer);
                }
            break;
            case 's' : $result = htmlspecialchars(get_field('aca_tv_results','student_out','id',$trid));
            break;
            case 't' : $result = htmlspecialchars(get_field('aca_tv_results','teacher_out','id',$trid));
            break;
        }
        
        if ($result) print_simple_box($result,'center','90%');
        else error('Invalid test result');
        
        print_footer('none');
    }
    
    /* THERE ARE FUNCTIONS FOR PLAGIAT DETECTORS */
    
    /**
     * function prints setting table for plagiat detectors module in view.php
     * @param object $assignment
     **/
    function print_pds_settings($assignment) {
        global $CFG;
        
        $acaid = $assignment->id;
        $langtype = $assignment->langtype;
        
        // get information about avail pds for lang
        $avail = get_records('aca_pds','langtype',$langtype,'id');
        if ($tmp = get_records('aca_pd_active','acaid',$acaid)) {
            //keys are changed to pdid
            foreach ($tmp as $key=>$val) {
                $active[$val->pdid] = $val;
            }
            unset($tmp);
        }
        
        if ($avail) {
            
            echo '<form name="pds" action="view.php?a='.$acaid.'" method="post">';
            echo '<input type="hidden" name="a" value="'.$acaid.'">';
                
            // create table heading
            $table->head = array(
                get_string('pdname','aca'),
                get_string('pdactive','aca'),
                get_string('pdborder','aca'),
                get_string('pdover','aca'),
                get_string('pdmodified','aca')
            );
            
            //array of options
            for ($i = 0;$i<=2;$i++) {
                $falseopt[$i]=get_string('pdfalseopt'.$i,'aca');
            }
            
            $acount = 0;
            // table data rows
            foreach ($avail as $id=>$pd) {
                $on = (isset($active[$id])); //active or not
                $table->data[$id][] = get_string('name'.$pd->name,'aca');
                // if method is enblad or disabled
                if ($on) {
                    $link = get_string('pdoff','aca');
                    $action = 'off&amp;pd='.$active[$id]->id;
                    $bordersel = $active[$id]->border;
                    $disable = '';
                    $modify = userdate($active[$id]->timemodified);
                    $falseval = $active[$id]->false_val;
                    $falseoptsel = $active[$id]->false_opt;
                    $name = '['.$active[$id]->id.']';
                    $acount++;
                }
                else {
                    $link = get_string('pdon','aca');
                    $linkid = '';
                    $action = 'on&amp;pdid='.$id;
                    $bordersel = $pd->resultdefault;
                    $disable = ' disabled="disabled"';
                    $modify = get_string('no');
                    $falseval = '0';
                    $falseoptsel = 0;
                    $name = '';
                }
                // assign data to row
                $table->data[$id][] = '<a href="view.php?a='.$acaid.'&amp;action='.$action.'">'.$link.'</a>';
                $minmax = range($pd->resultmin,$pd->resultmax);
                $table->data[$id][] = choose_from_menu ($minmax, 'border'.$name, $bordersel, '', '', '', true, !$on).'%';
                $table->data[$id][] = '<input type="text" size="3" name=false_val'.$name.' value="'.$falseval.'" '.$disable.'>&nbsp;'.
                                        choose_from_menu ($falseopt, 'false_opt'.$name, $falseoptsel, '', '', '', true, !$on);
                $table->data[$id][] = $modify;
            }
            $table->align=array('left','center','right','right','right');
            
            print_table($table);
            
            // save button
            echo '<table align="center"><tr><td>';
            //only if some pd is active
            if ($acount) echo '<input type="submit" value="'.get_string('savechanges').'">';
            echo '<input type="hidden" name="pdsetting" value="'.$acount.'">';
            echo '</td></tr></table>';
            echo '</form>';
        }
    }
        
    /**
     * function to save PD settings from $_POST vars
     **/
    function process_pds() {
        // get all vars to new item
        foreach ($_POST as $pkey=>$pval) {
            if (is_array($pval) && sizeof($pval)) {
                foreach($pval as $key=>$val) {
                    $data[$key]->$pkey = $val;
                }
                $data[$key]->id = $key;
                $data[$key]->timemodified = time();
            }
        }
        
        foreach ($data as $key=>$val) {
            if (!update_record('aca_pd_active',$val)) notify("$key not created");
        }
    }
    
    /**
     * function to insert new aca_pd_active row (if click method ON in settings table)
     * @param int $pdid ID of aca_pds table
     * @return none (insert data)
     **/
    function create_pd($pdid) {
        if ($pd = get_record('aca_pds','id',$pdid)) {
            $data->pdid = $pdid;
            $data->acaid = $this->assignment->id;
            $data->timemodified = time();
            $data->border = $pd->resultdefault;
            $data->false_opt = $data->false_val = 0;
            insert_record('aca_pd_active',$data);
        }
    }
    
    /**
     * function to delete aca_pd_active row (if click method OFF in settings table)
     * @param int $id ID of aca_pd_active table
     **/
    function delete_pd($id) {
        if ($id = get_field('aca_pd_active','id','id',$id)) {
            delete_records('aca_pd_active','id',$id,'acaid',$this->assignment->id);
        }
    }
    
    /* MODIFIED CODE FROM P4DM MODULE */
    
    /**
     * get_similarities()
     * function returns array of objects with similarities with other subs in course
     * @param int $assignment assignment ID
     * @param int $userid user ID
     * @return array $sims
     **/
    function get_similarities($assignment,$userid) {
        global $CFG;
    	if(count_records("aca_pd_similarity","acaid",$assignment,"id_pri",$userid)){
            $sql = "SELECT sims.*, ac.pdid as pdid FROM {$CFG->prefix}aca_pd_similarity as sims
                    LEFT JOIN {$CFG->prefix}aca_pd_active as ac ON
                    sims.activepdid = ac.id WHERE
                    sims.acaid = $assignment AND sims.id_pri=$userid ORDER BY
                    sims.activepdid,sims.id_sec,sims.similarity";
    		$sims=get_records_sql($sql);
    	}
    	return $sims;
    }
    
    /**
     * print_similarities()
     * function prints similarities with other subs for current sub
     * @param object $assignment
     * @param int $userid - user ID
     * @param bool $printform - prints to textarea or to page similarities.php
     * @return table of all similarities in all PD methods or the same text information
     **/
    function print_similarities($assignment,$userid,$printform = false,$format = false) {
        global $CFG;
        
        $out = '';
        
        if (!$printform) print_header(get_string('similarity','aca'));
        
        //get all pds methods
    	$methods = get_records('aca_pds','langtype',$assignment->langtype);
        
        $sims = $this->get_similarities($assignment->id,$userid);
            	
    	$first = true;
    	$table->head=array(get_string('similarwith','aca'),get_string('similarity','aca'));
    	$table->align=array('center','right');
    	foreach($sims as $sim) {
    		if (!$format)
    		{
    		
    		if($sim->similarity) {
    		    if ($first) {
    		        $lastid = $sim->pdid;
    		        $out .= ">>>".get_string('name'.$methods[$sim->pdid]->name,'aca')."\n";
    		        $first = false;
    		    }
    		    if ($lastid != $sim->pdid) {
    		        if (isset($table)) {
                        if (!$printform) {
                            print_heading(get_string('name'.$methods[$lastid]->name,'aca'));
                            print_table($table);
                        }
                        unset($table->data);
                    }
                    $lastid = $sim->pdid;
                    $out .= ">>>".get_string('name'.$methods[$sim->pdid]->name,'aca')."\n";
    		    }
    			$tmpuser = get_record("user", "id", "$sim->id_sec");
                if (!$printform) {
                    $table->data[$sim->id][] = fullname($tmpuser);
                    $table->data[$sim->id][] = $sim->similarity."&nbsp;%";
                }
                else {
                    $out .= fullname($tmpuser).': '.get_string('similarity','aca').' '.$sim->similarity.'%'."\n";
                }
    		}
    	}
    	else {
    	if($sim->similarity) {
    		    if ($first) {
    		        $lastid = $sim->pdid;
    		        $out .= "Výsledky kontroly plagiátů: <br/>\n";
    		        $first = false;
    		    }
    		    if ($lastid != $sim->pdid) {
                    $lastid = $sim->pdid;
                    $out .= "Výsledky kontroly plagiátů: <br/>".get_string('name'.$methods[$sim->pdid]->name,'aca')."\n";
    		    }
    			$tmpuser = get_record("user", "id", "$sim->id_sec");
                if (!$printform) {
                    $table->data[$sim->id][] = fullname($tmpuser);
                    $table->data[$sim->id][] = $sim->similarity."&nbsp;%";
                }
                else {
                    $out .= fullname($tmpuser).': '.get_string('similarity','aca').' '.$sim->similarity.'%'."<br/>\n";
                }
    		}
    	}
    	}
    	// buffered table data
    	if (!$printform) {
    	    if (isset($table) && sizeof($table->data)) {
                print_heading(get_string('name'.$methods[$lastid]->name,'aca'));
                print_table($table);
            }
    	}
    	
    	if (!$printform) print_footer('none');
    	else return $out;
    }
    
    /* YAP3 functions */
    
    /**
     * check_tokens_created()
     * check if tokens file is created in dir specified by newpath
     * @param int $acaid assignment id
     * @param int $userid user ID
     * @return bool tokens_created
     **/
    function check_tokens_created($acaid,$userid){
    	global $ACACFG;
    	if(file_exists("$ACACFG->newpath/$acaid/$userid.tokens"))
    		return true;
    	else return false;	
    }
    
    /**
     * function to delete tokens file for submission
     * @param object $submission
     **/
    function delete_tokens($submission){
    	global $newpath;
    	if(!unlink("$newpath/$submission->acaid/$submission->userid.tokens"))echo "error deleting";
    	else echo "deleted";
    }
    
    /**
     * create_tokens()
     * function create tokens file for one submission
     * called when user upload files
     * @param object $submisson
     * @param object $assignment
     * @return echo the result
     **/
    function create_tokens($submission,$assignment){
    	global $USER,$CFG,$ACACFG;
    	
		//get right tokenizer and function for tokenize
		$langtok = 'tokenizer_'.$assignment->langtype;
		$tokenizer = $ACACFG->$langtok;
				
        $tokens_file="$ACACFG->newpath/$assignment->id/$submission->userid.tokens";
		if(!is_dir("$ACACFG->newpath/$assignment->id")){
			mkdir("$ACACFG->newpath/$assignment->id",0777);
			chmod ("$ACACFG->newpath/$assignment->id",0777);
		}
		
		//copy all tokenized user files to tokentemp dir
		$sourcedir = $this->file_area_name($USER->id);
		$file_to_tokenize = '';
        $end = false;
        
        $handle = opendir($CFG->dataroot.'/'.$sourcedir);
        while (false !== ($file = readdir($handle))) {
            $ext=strtolower(strrchr($file,"."));
            if (in_array($ext,$ACACFG->tokenizeext)) {
                $end = @copy($CFG->dataroot.'/'.$sourcedir.'/'.$file,$ACACFG->tmppath.'/'.$file);
            }
            // get first tokenized file
            if ($end) {
                $file_to_tokenize = $ACACFG->tmppath.'/'.$file;
                break;
            }
        }
        closedir($handle);
				
		if ($file_to_tokenize != '') {
		
    	    $cmd="sh $tokenizer $file_to_tokenize > $tokens_file";
    	
    	    //exec command
    	    //echo "Command to execute: $cmd<br />";
            shell_exec($cmd);
    	    
            //delete all temp files
            $this->delete_all_files($ACACFG->tmppath);
    		    
    		//check if successfull
    		if(file_exists($tokens_file))
    			print_heading(get_string("tokenscreated", "aca"));
    		else notify(get_string("tokenscreationfailed", "aca"));
		}
    }
    
    /**
     * function to make all tokens if not created
     * @param object $assignment
     * @return echo the result
     **/
    function MakeTokens($assignment) {
    	global $CFG,$ACACFG;
    	
    	// some initialization
    	$ass=get_record("aca","id",$assignment);
    	$langtok = 'tokenizer_'.$ass->langtype;
    	$tokenizer = $ACACFG->$langtok;
    	    	
    	//dir to temp tokens
    	if(!is_dir("$ACACFG->newpath/$assignment")){
    		mkdir("$ACACFG->newpath/$assignment",0777);
    		chmod ("$ACACFG->newpath/$assignment",0777); 
    	}
    	
    	// iterate through all submissions dir
    	$acasubdir = $CFG->dataroot.'/'.substr($this->file_area_name(1,1),0,-7);
        $dir=@opendir($acasubdir);
        if(!$dir){
    		echo "Error during tokens directory opening";
    		return 0;
    	}
    	while (($file = readdir($dir))!==false) {
            if(is_dir("$acasubdir/$file")&&($file!="." && $file!=".." && $file!="source" && $file!="sourcetest")) {
    			// open students directory
                $studentdir=opendir("$acasubdir/$file");
    			if(!$studentdir)die("dir not open");
    			$cmd = '';
    			while(($subfile=readdir($studentdir))!==false) {
    				$ext=strtolower(strrchr($subfile,"."));
    				if (in_array($ext,$ACACFG->tokenizeext)) {
    					$cmd="sh $tokenizer $acasubdir/$file/$subfile > $ACACFG->newpath/$assignment/$file.tokens";
    					//chmod ($PD4MCFG->newpath/$assignment/$file.tokens,0777);
    					//echo "Command to execute: $cmd<br />";
                        exec($cmd);
    				}
    				if ($cmd != '') break;
    			}
    			closedir($studentdir);
    		}
    	}
    	closedir($dir);
    	return true;
    }
    
    /**
     * function to execute rkr_gst program for all created tokens
     * @param int $assignment ID od assignment
     * @return none - execute command
     **/
    function ExecYap($assignment){
    	global $ACACFG;
    	
    	@unlink("$ACACFG->newpath/$assignment/yap.newfiles");
    	@unlink("$ACACFG->newpath/$assignment/yap.numbers");
    	@unlink("$ACACFG->newpath/$assignment/yap.status");
    	@unlink("$ACACFG->newpath/$assignment/yap.submissions");
    	@unlink("$ACACFG->newpath/$assignment/yap.summary");
    	
    	//unset($sims,$sim);
    	//$currentdir=getcwd();
    	//chdir(dirname($simchecker));	
    	$cmd="sh $ACACFG->simchecker $ACACFG->newpath $assignment";
    	//chdir($currentdir);
    	//echo "Command to execute: $cmd<br />";
        exec($cmd,$sims);
    	//foreach($sims as $sim)echo "[$sim]<br>";
    }
    
    /**
     * LoadYapSummary()
     * function loads yap.summary file from directory specified newpath and assignment id 
     * and insert data into db table assignment_submissions_similarity
     * @param int $assignment ID of assignment
     * @param int $pdid - pdid column of aca_pd_active table
     * @return none - insert data to DB
     **/
    function LoadYapSummary($assignment,$pdid){
    	global $ACACFG;
    	
    	if(file_exists("$ACACFG->newpath/$assignment/yap.summary")){
    		$summary_file=fopen("$ACACFG->newpath/$assignment/yap.summary","r");
    		if(!$summary_file){
    			echo "<h3>Error during opening file with detection summary</h3>";
    			return 0;
    		}
    	}
    	else {
    		echo "<h3>File with detection summary does not exists</h3><br/>File: $ACACFG->newpath/$assignment/yap.summary";
    		return 0;
    	}
    	echo "<pre>";
    	// delete old values for this method
    	delete_records("aca_pd_similarity","acaid",$assignment,'activepdid',$pdid);
    	
    	// info about current active PD
        $active=get_record("aca_pd_active","acaid",$assignment,'id',$pdid);
    	
    	$simobj->acaid=$assignment;
    	$simobj->activepdid=$active->id;
    	$simlimit = $active->border;
        
        // parse yap.summary file
    	while(($line=fgets($summary_file,4096))!==false){
    		unset($part,$linetok);
    		$line=chop($line);
    		$part = strtok ($line," ");
    		while ($part) {
       			$linetok[]=$part;
    	   		$part = strtok (" ");
    		} 
    		$sub1=substr($linetok[0],strrpos($linetok[0],"/")+1,strrpos($linetok[0],".token")-strrpos($linetok[0],"/")-1);
    		$sub2=substr($linetok[1],strrpos($linetok[1],"/")+1,strrpos($linetok[1],".token")-strrpos($linetok[1],"/")-1);
    		$similarity=$linetok[2];
    		if($similarity>100)$similarity=100;
    		
    		if($similarity>=$simlimit){
    			                
                if(count_records("aca_pd_similarity","acaid",$assignment,"id_pri",$sub1,"id_sec",$sub2)>0){
                    $simobj->id_pri=$sub1;
    				$simobj->id_sec=$sub2;
    				$simobj->similarity=$similarity;
    				update_record("aca_pd_similarity",$simobj);
    			}
    			else{
    				$simobj->id_pri=$sub1;
    				$simobj->id_sec=$sub2;
    				$simobj->similarity=$similarity;
    				insert_record("aca_pd_similarity",$simobj);
    			}
    		}
    	}
    	echo "</pre>";
    	fclose($summary_file);
    }
    
    /**
     * function prints button to make all tests
     * @param object $asignment
     **/
    function print_makealltokens_button($assignment) {
        echo "<form action=\"pd4m.make.php\" method=\"get\" target=_blank>";
        echo "<center>";
        echo "<input type=hidden name=id value=\"$assignment->id\">";
		echo "<input type=hidden name=w value=\"maketokens\">";
        echo "<input type=submit value=\"".get_string("makealltokens","aca")."\">";
        echo "</center></form>";
    }
    /**
     * function prints button to make all summaries
     * @param object $asignment
     **/
    function print_makesummary_button($assignment){
        echo "<form action=\"pd4m.make.php\" method=\"get\" target=_blank>";
        echo "<center>";
        echo "<input type=hidden name=id value=\"$assignment->id\">";
		echo "<input type=hidden name=w value=\"execyap\">";
        echo "<input type=submit value=\"".get_string("execyap","aca")."\">";
        echo "</center></form>";
    }
    /**
     * function prints form to load summary from file
     * @param object $asignment
     **/
    function print_loadsummary_button($assignment){
        echo "<form action=\"pd4m.make.php\" method=\"get\" target=_blank>";
        echo "<center>";
        echo "<input type=hidden name=id value=\"$assignment->id\">";
		echo "<input type=hidden name=w value=\"loadyap\">";
        echo "<input type=submit value=\"".get_string("loadyapsummary","aca")."\">";
        echo "</center></form>";
    }
    /**
     * function prints buttons to export or import files
     * @param object $asignment
     **/
    function print_exportimport_buttons($assignment){
        echo "<form action=\"pd4m.make.php\" method=\"get\" target=_blank>";
        echo "<center>";
        echo "<input type=hidden name=id value=\"$assignment->id\">";
        echo "<input type=hidden name=w value=\"export\">";
        echo "<input type=submit value=\"".get_string("exporttokens","aca")."\">";
        echo "</form>";
        
        echo "<form action=\"pd4m.make.php\" method=\"get\" target=_blank>";
        echo "<input type=hidden name=id value=\"$assignment->id\">";
        echo "<input type=hidden name=w value=\"import\">";
        echo "<input type=submit value=\"".get_string("importtokens","aca")."\">";
        echo "</form></center>";	
    }
    
    /**
     * function to process all PDs - in submission page
     * return similarities between files
     * switched by PDID
     * each method for each language calls his own functions
     * @param int $assignment ID of assignment
     **/
    function process_all_pds($assignment) {
        if ($active = get_records('aca_pd_active','acaid',$assignment)) {
            foreach ($active as $pd) {
                switch ($pd->pdid) {
                    case 1: {   //yap php
                        $this->ExecYap($assignment);
                        $this->LoadYapSummary($assignment,$pd->id);
                    }
                    break;
                    case 2: {   //yap c
                        $this->ExecYap($assignment);
                        $this->LoadYapSummary($assignment,$pd->id);
                    }
                    break;
                    case 3: {   //yap pascal
                        $this->ExecYap($assignment);
                        $this->LoadYapSummary($assignment,$pd->id);
                    }
                }
                // grade it
                $this->grade_after_pd($assignment,$pd->pdid);
            }
        }
    }
    
    /**
     * function to grade submissions
     * @param int $assignment ID of assignment
     * @param int $pdid PD method ID
     **/
    function grade_after_pd($assignment,$pdid) {
        $grademax = $this->assignment->grade; // maximal grade for this assignment
        
        //get active PD for this assig.
        if ($actpd = get_record('aca_pd_active','acaid',$assignment,'pdid',$pdid)) {
            // get all submissions
            $newsub = array();
            if ($subs = get_records('aca_submissions','acaid',$assignment)) {
                foreach ($subs as $sub) {
                    //if is in sim table
                    if (count_records('aca_pd_similarity','id_pri',$sub->userid,'acaid',$assignment)) {
                        // types of possible grade types
                        switch ($actpd->false_opt) {
                            case 0: $newgrade = false;
                            break;
                            case 1: { 
                                if ($actpd->false_val < $sub->grade)
                                {
                                	$newgrade = $actpd->false_val;
                                	//echo "<br/><br/>--- 1 - $newgrade ---<br/><br/>";
                                }
                                else
                                {
                                	$newgrade = false;
                                	//echo "<br/><br/>--- 2 ---<br/><br/>";
                                }
                            }
                            break;
                            case 2: {
                                $newgrade = round($grademax*($actpd->false_val/100));
                                if ($newgrade > $sub->grade) $newgrade = false;
                            }
                            break;
                        }
                        // save new grade to DB
                        if ($newgrade !== false) $newsub[$sub->id] = $newgrade;
                    }
                }
                
                /// Load up the required assignment code
   				//require('/home/bakalarka/moodle/mod/aca/type/'.$this->assignment->langtype.'/aca.class.php');
    			//$acaclass = 'aca_'.$this->assignment->langtype;
    			//$acainstance = new $acaclass($cm->id, $this->assignment, $cm, $course);
    			
    			//echo "<br/><br/>$this->print_similarities($assignment,$sub->userid,true);---<br/><br/>";
    			$comment = $this->print_similarities($this->assignment,$sub->userid,true,true);
                //$comment = "Plagiát";
                
                // update if we have some data
                if (sizeof($newsub)) {
                    foreach ($newsub as $key=>$val) {
                        $nsub->id = $key;
                        $nsub->grade = $val;
                        $nsub->comment = $comment;
                        update_record('aca_submissions',$nsub);
                    }
                }
            }
        }
    }
    
    /** 
     * function to preprocess file for PD module - only one submission
     * typically called when user upload file
     * switched by PDID (method)
     * @param object $assignment
     * @paran object $submission
     **/
    function preprocess_pd_files($assignment,$submission) {
        if ($active = get_records('aca_pd_active','acaid',$assignment->id)) {
            foreach ($active as $pd) {
                switch ($pd->pdid) {
                    case 1: {   //yap php
                        $this->create_tokens($submission,$assignment);
                    }
                    break;
                    case 2: {   //yap c
                        $this->create_tokens($submission,$assignment);
                    }
                    break;
                    case 3: {   //yap pascal
                        $this->create_tokens($submission,$assignment);
                    }
                    break;
                }
                
            }
        }
    }
    
    /* OTHER ADDITIONAL FUNCTIONS */
    
    /**
     * function shows "readable" information about differences from diff -p command
     * it shows ONLY DIFFERENT lines and number of missed lines
     * @param array $buffer (typicaly from file() function
     * @return HTML formated string
     **/
    function showdiff($buffer) {
        $return='';
        
        if (is_array($buffer)) {
            $row=0;
            $hlp=0;
            $missed=0;
            $text = '';
            foreach ($buffer as $line) {
                if (ereg("^---",$line)) {
                    ++$hlp;
                }
                if ($hlp==1) {
                    if (ereg("^- ",$line)) {
                        ++$missed;
                    }
                }
                if ($hlp==2) {
                    ++$row;
                    if (ereg("^!",$line)) {
                        $line=ereg_replace("^! ()","\\1",$line);
                        $line = htmlspecialchars($line);
                        $text=$text.get_string("line","aca")." ".$row.": ".$line."<br />";
                    } elseif (ereg("^\+",$line)) {
                        $line=ereg_replace("^\+ ()","\\1",$line);
                        $line = htmlspecialchars($line);
                        $text=$text.get_string("line","aca")." ".$row.": ".$line." ...".get_string("isextra","aca")."!<br />"; 
                    }
                }
            }
          
            if ($missed) {
                $text=$text."<br /><br />".get_string("numofmissed","aca").": ".$missed."<br />";
            }
            $return=get_string("testnotok","aca").":<br />".$text;
        }
        else $return = get_string("testok","aca");
        
        return $return;
    }
    
    /**
     * function to copy all files from dir to dir
     * @param array $files - array of files to copy
     * @param path $from_dir - source dir
     * @param path $dest_dir - destination dir
     * @return bool success
     **/
    function copy_all_files($files,$from_dir,$dest_dir) {
        $res = true;
        foreach ($files as $file) {
            $res &= @copy($from_dir.'/'.$file,$dest_dir.'/'.$file);
        }
        return $res;
    }
    
    /**
     * function to delete all files in dir
     * @param path $dir - dir to delete
     **/
    function delete_all_files($dir) {
        $res = true;
        $handle = opendir($dir);
        while (false !== ($file = readdir($handle))) {
            if ($file!='.' && $file!= '..') $res &= @unlink($dir.'/'.$file);
        }
        return $res;
    }

} ////// End of the assignment_base class



/// OTHER STANDARD FUNCTIONS ////////////////////////////////////////////////////////


function aca_delete_instance($id){
    global $CFG;

    if (! $assignment = get_record('aca', 'id', $id)) {
        return false;
    }

    require_once("$CFG->dirroot/mod/aca/type/$assignment->langtype/aca.class.php");
    $acaclass = "aca_$assignment->langtype";
    $ass = new $acaclass();
    return $ass->delete_instance($assignment);
}

function aca_update_instance($assignment){
    global $CFG,$ACACFG;

    $assignment->langtype = clean_param($assignment->langtype, PARAM_SAFEDIR);

    require_once("$CFG->dirroot/mod/aca/type/$assignment->langtype/aca.class.php");
    $acaclass = "aca_$assignment->langtype";
    $ass = new $acaclass();
    return $ass->update_instance($assignment);
}    

function aca_add_instance($assignment) {
    global $CFG,$ACACFG;

    $assignment->langtype = clean_param($assignment->langtype, PARAM_SAFEDIR);

    require_once("$CFG->dirroot/mod/aca/type/$assignment->langtype/aca.class.php");
    $acaclass = "aca_$assignment->langtype";
    $ass = new $acaclass();
    return $ass->add_instance($assignment);
}

function aca_user_outline($course, $user, $mod, $assignment) {
    global $CFG;

    require_once("$CFG->dirroot/mod/aca/type/$assignment->langtype/aca.class.php");
    $acaclass = "aca_$assignment->langtype";
    $ass = new $acaclass($mod->id, $assignment, $mod, $course);
    return $ass->user_outline($user);
}

function aca_user_complete($course, $user, $mod, $assignment) {
    global $CFG;

    require_once("$CFG->dirroot/mod/aca/type/$assignment->langtype/aca.class.php");
    $acaclass = "aca_$assignment->langtype";
    $ass = new $acaclass($mod->id, $assignment, $mod, $course);
    return $ass->user_complete($user);
}

function aca_cron () {
// Function to be run periodically according to the moodle cron
// Finds all assignment notifications that have yet to be mailed out, and mails them

    global $CFG, $USER;

    /// Notices older than 1 day will not be mailed.  This is to avoid the problem where
    /// cron has not been running for a long time, and then suddenly people are flooded
    /// with mail from the past few weeks or months

    $timenow   = time();
    $endtime   = $timenow - $CFG->maxeditingtime;
    $starttime = $endtime - 24 * 3600;   /// One day earlier

    if ($submissions = aca_get_unmailed_submissions($starttime, $endtime)) {

        foreach ($submissions as $key => $submission) {
            if (! set_field("aca_submissions", "mailed", "1", "id", "$submission->id")) {
                echo "Could not update the mailed field for id $submission->id.  Not mailed.\n";
                unset($submissions[$key]);
            }
        }

        $timenow = time();

        foreach ($submissions as $submission) {

            echo "Processing assignment submission $submission->id\n";

            if (! $user = get_record("user", "id", "$submission->userid")) {
                echo "Could not find user $post->userid\n";
                continue;
            }

            $USER->lang = $user->lang;

            if (! $course = get_record("course", "id", "$submission->course")) {
                echo "Could not find course $submission->course\n";
                continue;
            }

            if (! isstudent($course->id, $user->id) and !isteacher($course->id, $user->id)) {
                echo fullname($user)." not an active participant in $course->shortname\n";
                continue;
            }

            if (! $teacher = get_record("user", "id", "$submission->teacher")) {
                echo "Could not find teacher $submission->teacher\n";
                continue;
            }

            if (! $mod = get_coursemodule_from_instance("aca", $submission->assignment, $course->id)) {
                echo "Could not find course module for assignment id $submission->assignment\n";
                continue;
            }

            if (! $mod->visible) {    /// Hold mail notification for hidden assignments until later
                continue;
            }

            $strassignments = get_string("modulenameplural", "aca");
            $strassignment  = get_string("modulename", "aca");

            unset($assignmentinfo);
            $assignmentinfo->teacher = fullname($teacher);
            $assignmentinfo->assignment = format_string($submission->name,true);
            $assignmentinfo->url = "$CFG->wwwroot/mod/aca/view.php?id=$mod->id";

            $postsubject = "$course->shortname: $strassignments: ".format_string($submission->name,true);
            $posttext  = "$course->shortname -> $strassignments -> ".format_string($submission->name,true)."\n";
            $posttext .= "---------------------------------------------------------------------\n";
            $posttext .= get_string("acamail", "aca", $assignmentinfo);
            $posttext .= "---------------------------------------------------------------------\n";

            if ($user->mailformat == 1) {  // HTML
                $posthtml = "<p><font face=\"sans-serif\">".
                "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> ->".
                "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id=$course->id\">$strassignments</a> ->".
                "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=$mod->id\">".format_string($submission->name,true)."</a></font></p>";
                $posthtml .= "<hr /><font face=\"sans-serif\">";
                $posthtml .= "<p>".get_string("acamailhtml", "aca", $assignmentinfo)."</p>";
                $posthtml .= "</font><hr />";
            } else {
                $posthtml = "";
            }

            if (! email_to_user($user, $teacher, $postsubject, $posttext, $posthtml)) {
                echo "Error: assignment cron: Could not send out mail for id $submission->id to user $user->id ($user->email)\n";
            }
        }
    }

    return true;
}

function aca_grades($assignmentid) {
/// Must return an array of grades, indexed by user, and a max grade.

    if (!$assignment = get_record('aca', 'id', $assignmentid)) {
        return NULL;
    }
    if ($assignment->grade == 0) { // No grading
        return NULL;
    }

    $grades = get_records_menu('aca_submissions', 'acaid',
                               $assignment->id, '', 'userid,grade');

    if ($assignment->grade > 0) {
        if ($grades) {
            foreach ($grades as $userid => $grade) {
                if ($grade == -1) {
                    $grades[$userid] = '-';
                }
            }
        }
        $return->grades = $grades;
        $return->maxgrade = $assignment->grade;

    } else { // Scale
        if ($grades) {
            $scaleid = - ($assignment->grade);
            if ($scale = get_record('scale', 'id', $scaleid)) {
                $scalegrades = make_menu_from_list($scale->scale);
                foreach ($grades as $userid => $grade) {
                    if (empty($scalegrades[$grade])) {
                        $grades[$userid] = '-';
                    } else {
                        $grades[$userid] = $scalegrades[$grade];
                    }
                }
            }
        }
        $return->grades = $grades;
        $return->maxgrade = "";
    }

    return $return;
}

function aca_get_participants($assignmentid) {
//Returns the users with data in one assignment
//(users with records in assignment_submissions, students and teachers)

    global $CFG;

    //Get students
    $students = get_records_sql("SELECT DISTINCT u.id, u.id
                                 FROM {$CFG->prefix}user u,
                                      {$CFG->prefix}aca_submissions a
                                 WHERE a.acaid = '$assignmentid' and
                                       u.id = a.userid");
    //Get teachers
    $teachers = get_records_sql("SELECT DISTINCT u.id, u.id
                                 FROM {$CFG->prefix}user u,
                                      {$CFG->prefix}aca_submissions a
                                 WHERE a.acaid = '$assignmentid' and
                                       u.id = a.teacher");

    //Add teachers to students
    if ($teachers) {
        foreach ($teachers as $teacher) {
            $students[$teacher->id] = $teacher;
        }
    }
    //Return students array (it contains an array of unique users)
    return ($students);
}

function aca_scale_used ($assignmentid,$scaleid) {
//This function returns if a scale is being used by one assignment

    $return = false;

    $rec = get_record('aca','id',$assignmentid,'grade',-$scaleid);

    if (!empty($rec) && !empty($scaleid)) {
        $return = true;
    }

    return $return;
}

function aca_refresh_events($courseid = 0) {
// This standard function will check all instances of this module
// and make sure there are up-to-date events created for each of them.
// If courseid = 0, then every assignment event in the site is checked, else
// only assignment events belonging to the course specified are checked.
// This function is used, in its new format, by restore_refresh_events()

    if ($courseid == 0) {
        if (! $assignments = get_records("aca")) {
            return true;
        }
    } else {
        if (! $assignments = get_records("aca", "course", $courseid)) {
            return true;
        }
    }
    $moduleid = get_field('modules', 'id', 'name', 'aca');

    foreach ($assignments as $assignment) {
        $event = NULL;
        $event->name        = addslashes($assignment->name);
        $event->description = addslashes($assignment->description);
        $event->timestart   = $assignment->timedue;

        if ($event->id = get_field('event', 'id', 'modulename', 'aca', 'instance', $assignment->id)) {
            update_event($event);

        } else {
            $event->courseid    = $assignment->course;
            $event->groupid     = 0;
            $event->userid      = 0;
            $event->modulename  = 'aca';
            $event->instance    = $assignment->id;
            $event->eventtype   = 'due';
            $event->timeduration = 0;
            $event->visible     = get_field('course_modules', 'visible', 'module', $moduleid, 'instance', $assignment->id);
            add_event($event);
        }

    }
    return true;
}

function aca_print_recent_activity($course, $isteacher, $timestart) {
    global $CFG;

    $content = false;
    $assignments = NULL;

    if (!$logs = get_records_select('log', 'time > \''.$timestart.'\' AND '.
                                           'course = \''.$course->id.'\' AND '.
                                           'module = \'aca\' AND '.
                                           'action = \'upload\' ', 'time ASC')) {
        return false;
    }

    foreach ($logs as $log) {
        //Create a temp valid module structure (course,id)
        $tempmod->course = $log->course;
        $tempmod->id = $log->info;
        //Obtain the visible property from the instance
        $modvisible = instance_is_visible($log->module,$tempmod);

        //Only if the mod is visible
        if ($modvisible) {
            $assignments[$log->info] = aca_log_info($log);
            $assignments[$log->info]->time = $log->time;
            $assignments[$log->info]->url  = str_replace('&', '&amp;', $log->url);
        }
    }

    if ($assignments) {
        print_headline(get_string('newsubmissions', 'aca').':');
        foreach ($assignments as $assignment) {
            print_recent_activity_note($assignment->time, $assignment, $isteacher, $assignment->name,
                                       $CFG->wwwroot.'/mod/aca/'.$assignment->url);
        }
        $content = true;
    }

    return $content;
}


function aca_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $assignment="0", $user="", $groupid="")  {
// Returns all assignments since a given time.  If assignment is specified then
// this restricts the results

    global $CFG;

    if ($assignment) {
        $assignmentselect = " AND cm.id = '$assignment'";
    } else {
        $assignmentselect = "";
    }
    if ($user) {
        $userselect = " AND u.id = '$user'";
    } else {
        $userselect = "";
    }

    $assignments = get_records_sql("SELECT asub.*, u.firstname, u.lastname, u.picture, u.id as userid,
                                           a.grade as maxgrade, name, cm.instance, cm.section, a.langtype
                                  FROM {$CFG->prefix}aca_submissions asub,
                                       {$CFG->prefix}user u,
                                       {$CFG->prefix}aca a,
                                       {$CFG->prefix}course_modules cm
                                 WHERE asub.timemodified > '$sincetime'
                                   AND asub.userid = u.id $userselect
                                   AND a.id = asub.acaid $assignmentselect
                                   AND cm.course = '$courseid'
                                   AND cm.instance = a.id
                                 ORDER BY asub.timemodified ASC");

    if (empty($assignments))
      return;

    foreach ($assignments as $assignment) {
        if (empty($groupid) || ismember($groupid, $assignment->userid)) {

          $tmpactivity = new Object;

          $tmpactivity->type = "aca";
          $tmpactivity->defaultindex = $index;
          $tmpactivity->instance = $assignment->instance;
          $tmpactivity->name = $assignment->name;
          $tmpactivity->section = $assignment->section;

          $tmpactivity->content->grade = $assignment->grade;
          $tmpactivity->content->maxgrade = $assignment->maxgrade;
          $tmpactivity->content->type = $assignment->langtype;

          $tmpactivity->user->userid = $assignment->userid;
          $tmpactivity->user->fullname = fullname($assignment);
          $tmpactivity->user->picture = $assignment->picture;

          $tmpactivity->timestamp = $assignment->timemodified;

          $activities[] = $tmpactivity;

          $index++;
        }
    }

    return;
}


function aca_print_recent_mod_activity($activity, $course, $detail=false)  {
    global $CFG;

    echo '<table border="0" cellpadding="3" cellspacing="0">';

    echo "<tr><td class=\"userpicture\" width=\"35\" valign=\"top\">";
    print_user_picture($activity->user->userid, $course, $activity->user->picture);
    echo "</td><td width=\"100%\"><font size=2>";

    if ($detail) {
        echo "<img src=\"$CFG->modpixpath/$activity->type/icon.gif\" ".
             "height=16 width=16 alt=\"$activity->type\">  ";
        echo "<a href=\"$CFG->wwwroot/mod/aca/view.php?id=" . $activity->instance . "\">"
             . format_string($activity->name,true) . "</a> - ";

    }

    if (isteacher($course)) {
        $grades = "(" .  $activity->content->grade . " / " . $activity->content->maxgrade . ") ";

        $assignment->id = $activity->instance;
        $assignment->course = $course;
        $user->id = $activity->user->userid;

        echo $grades;
        echo "<br />";
    }
    echo "<a href=\"$CFG->wwwroot/user/view.php?id="
         . $activity->user->userid . "&amp;course=$course\">"
         . $activity->user->fullname . "</a> ";

    echo " - " . userdate($activity->timestamp);

    echo "</font></td></tr>";
    echo "</table>";

    return;
}

/// GENERIC SQL FUNCTIONS

function aca_log_info($log) {
    global $CFG;
    return get_record_sql("SELECT a.name, u.firstname, u.lastname
                             FROM {$CFG->prefix}aca a, 
                                  {$CFG->prefix}user u
                            WHERE a.id = '$log->info' 
                              AND u.id = '$log->userid'");
}

function aca_get_unmailed_submissions($starttime, $endtime) {
/// Return list of marked submissions that have not been mailed out for currently enrolled students
    global $CFG;
    return get_records_sql("SELECT s.*, a.course, a.name
                              FROM {$CFG->prefix}aca_submissions s, 
                                   {$CFG->prefix}aca a,
                                   {$CFG->prefix}user us
                             WHERE s.mailed = 0 
                               AND s.timemarked <= $endtime
                               AND s.timemarked >= $starttime
                               AND s.acaid = a.id
                               AND s.userid = us.id");
}

function aca_count_real_submissions($assignment, $groupid=0) {
/// Return all real assignment submissions by ENROLLED students (not empty ones)
    global $CFG;

    if ($groupid) {     /// How many in a particular group?
        return count_records_sql("SELECT COUNT(DISTINCT g.userid, g.groupid)
                                     FROM {$CFG->prefix}aca_submissions a,
                                          {$CFG->prefix}groups_members g
                                    WHERE a.acaid = $assignment->id 
                                      AND a.timemodified > 0
                                      AND g.groupid = '$groupid' 
                                      AND a.userid = g.userid ");
    } else {
        $select = "s.course = '$assignment->course' AND";
        if ($assignment->course == SITEID) {
            $select = '';
        }
        return count_records_sql("SELECT COUNT(*)
                                  FROM {$CFG->prefix}aca_submissions a, 
                                       {$CFG->prefix}user_students s
                                 WHERE a.acaid = '$assignment->id' 
                                   AND a.timemodified > 0
                                   AND $select a.userid = s.userid ");
    }
}

function aca_get_all_submissions($assignment, $sort="", $dir="DESC") {
/// Return all assignment submissions by ENROLLED students (even empty)
    global $CFG;

    if ($sort == "lastname" or $sort == "firstname") {
        $sort = "u.$sort $dir";
    } else if (empty($sort)) {
        $sort = "a.timemodified DESC";
    } else {
        $sort = "a.$sort $dir";
    }

    $select = "s.course = '$assignment->course' AND";
    if ($assignment->course == SITEID) {
        $select = '';
    }
    return get_records_sql("SELECT a.* 
                              FROM {$CFG->prefix}aca_submissions a, 
                                   {$CFG->prefix}user_students s,
                                   {$CFG->prefix}user u
                             WHERE a.userid = s.userid
                               AND u.id = a.userid
                               AND $select a.acaid = '$assignment->id' 
                          ORDER BY $sort");
}


/// OTHER GENERAL FUNCTIONS FOR ASSIGNMENTS  ///////////////////////////////////////

// get array of available prog. lang. modules
function aca_types() {
    $types = array();
    $names = get_list_of_plugins('mod/aca/type');
    foreach ($names as $name) {
        $types[$name] = get_string('type'.strtolower($name), 'aca');
    }
    asort($types);
    return $types;
}

function aca_upgrade_submodules() {
    global $CFG;

    $types = aca_types();

    include($CFG->dirroot.'/mod/aca/version.php');  // defines $module with version etc

    foreach ($types as $type => $typename) {

        $fullpath = $CFG->dirroot.'/mod/aca/type/'.$type;

    /// Check for an external version file (defines $submodule)

        if (!is_readable($fullpath .'/version.php')) {
            continue;
        }
        include_once($fullpath .'/version.php');

    /// Check whether we need to upgrade

        if (!isset($submodule->version)) {
            continue;
        }

    /// Make sure this submodule will work with this assignment version

        if (isset($submodule->requires) and ($submodule->requires > $module->version)) {
            notify("AC Assignment submodule '$type' is too new for your ac assignment");
            continue;
        }

    /// If the submodule is new, then let's install it!

        $currentversion = 'aca_'.$type.'_version';

        if (!isset($CFG->$currentversion)) {   // First install!
            set_config($currentversion, $submodule->version);  // Must keep track of version

            if (!is_readable($fullpath .'/db/'.$CFG->dbtype.'.sql')) {
                continue;
            }

            $db->debug=true;
            if (!modify_database($fullpath .'/db/'.$CFG->dbtype.'.sql')) {
                notify("Error installing tables for submodule '$type'!");
            }
            $db->debug=false;
            continue;
        }

    /// See if we need to upgrade
        
        if ($submodule->version <= $CFG->$currentversion) {
            continue;
        }

    /// Look for the upgrade file

        if (!is_readable($fullpath .'/db/'.$CFG->dbtype.'.php')) {
            continue;
        }

        include_once($fullpath .'/db/'. $CFG->dbtype .'.php');  // defines aca_xxx_upgrade

    /// Perform the upgrade

        $upgrade_function = 'aca_'.$type.'_upgrade';
        if (function_exists($upgrade_function)) {
            $db->debug=true;
            if ($upgrade_function($CFG->$currentversion)) {
                $db->debug=false;
                set_config($currentversion, $submodule->version);
            }
            $db->debug=false;
        }
    }
}

?>
